QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SurfacePatchModel.h
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 *
5 * QGroundControl is licensed according to the terms in the file
6 * COPYING.md in the root of the source code directory.
7 *
8 ****************************************************************************/
9
10#pragma once
11
12#include <QtCore/QAbstractListModel>
13#include <QtCore/QElapsedTimer>
14#include <QtCore/QHash>
15#include <QtCore/QList>
16#include <QtCore/QPointF>
17#include <QtCore/QSet>
18#include <QtCore/QString>
19#include <QtCore/QStringList>
20#include <QtGui/QImage>
21#include <QtQmlIntegration/QtQmlIntegration>
22
23#include "TileMath.h"
24
25class GeoScene;
26class GeoMapCamera;
27class HeightField;
28class HeightSource;
29class QNetworkAccessManager;
30class QTimer;
31class SurfaceModel;
32class TileImageSource;
33
34Q_MOC_INCLUDE("GeoMapCamera.h")
35Q_MOC_INCLUDE("GeoScene.h")
36Q_MOC_INCLUDE("HeightField.h")
37
43class SurfacePatchModel : public QAbstractListModel
44{
45 Q_OBJECT
46 QML_ELEMENT
47 Q_PROPERTY(GeoScene* scene READ scene WRITE setScene NOTIFY sceneChanged)
48 Q_PROPERTY(bool terrain READ terrain WRITE setTerrain NOTIFY terrainChanged)
49 Q_PROPERTY(bool debugHills READ debugHills WRITE setDebugHills NOTIFY debugHillsChanged)
50 Q_PROPERTY(QString mapType READ mapType WRITE setMapType NOTIFY mapTypeChanged)
51 Q_PROPERTY(int gridSize READ gridSize CONSTANT)
52 Q_PROPERTY(double maxRangeMultiplier READ maxRangeMultiplier CONSTANT)
53 Q_PROPERTY(int patchCount READ patchCount NOTIFY statsChanged)
54 Q_PROPERTY(int pendingCount READ pendingCount NOTIFY statsChanged)
55 Q_PROPERTY(int maxZoomLevel READ maxZoomLevel NOTIFY statsChanged)
56 Q_PROPERTY(bool statsEnabled READ statsEnabled WRITE setStatsEnabled NOTIFY statsEnabledChanged)
57 Q_PROPERTY(QString statsText READ statsText NOTIFY statsTextChanged)
58 Q_PROPERTY(bool capturing READ capturing NOTIFY capturingChanged)
59
60public:
61 explicit SurfacePatchModel(QObject* parent = nullptr);
63
79
80 GeoScene* scene() const { return _scene; }
81
82 void setScene(GeoScene* scene);
83
84 bool terrain() const { return _terrain; }
85
88 void setTerrain(bool terrain);
89
90 bool debugHills() const { return _debugHills; }
91
92 void setDebugHills(bool debugHills);
93
94 QString mapType() const { return _mapType; }
95
98 void setMapType(const QString& mapType);
99
100 int gridSize() const;
101
104 HeightField* heightField() const { return _heightField; }
105
110 Q_INVOKABLE double terrainHeightAt(const QGeoCoordinate& coordinate) const;
111
116 Q_INVOKABLE double terrainDataHeightAt(const QGeoCoordinate& coordinate) const;
117
122 Q_INVOKABLE bool segmentBelowTerrain(const QGeoCoordinate& from, const QGeoCoordinate& to, double ignoreStartMeters,
123 double ignoreEndMeters) const;
124
132 Q_INVOKABLE QGeoCoordinate surfaceCoordinateAtScreenPoint(const GeoMapCamera* camera, const QPointF& screenPos,
133 double zScale) const;
134
137 double maxRangeMultiplier() const;
138
139 int patchCount() const { return _keys.count(); }
140
141 int pendingCount() const;
142 int maxZoomLevel() const;
143
145 int pendingImageCount() const { return _imageRequestKey.count(); }
146
149 void setTileImageNetworkManager(QNetworkAccessManager* networkManager)
150 {
151 _tileImageNetworkManager = networkManager;
152 }
153
154 bool statsEnabled() const { return _statsEnabled; } // GCOVR_EXCL_LINE
155
158 void setStatsEnabled(bool enabled);
159
160 QString statsText() const { return _statsText; }
161
162 bool capturing() const { return _capturing; }
163
165 Q_INVOKABLE void startCapture();
166
169 Q_INVOKABLE QString stopCapture();
170
174 Q_INVOKABLE void analyzeSurface() const;
175
176#ifdef QGC_UNITTEST_BUILD
178 void drainUpdates();
179#endif
180
181 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
182 QVariant data(const QModelIndex& index, int role) const override;
183 QHash<int, QByteArray> roleNames() const override;
184
185signals:
198
199private slots:
200 void _patchAdded(const TileMath::TileKey& key);
201 void _patchReady(const TileMath::TileKey& key);
202 void _patchEdgeDeltasChanged(const TileMath::TileKey& key);
203 void _patchRemoved(const TileMath::TileKey& key);
204 void _sceneOriginChanged();
205 void _tileImageReady(int requestId, const QImage& image);
206 void _tileImageFailed(int requestId);
207 void _statsTick();
208
209private:
210 void _rebuildSurfaceModel();
211 double _surfaceHeightAt(const QPointF& world) const;
212 void _resetImagery();
213 void _requestTileImage(const TileMath::TileKey& key);
214 void _retryFailedImages();
215 void _notifyTileImageChanged(const TileMath::TileKey& key);
216 void _invalidateFallbacks(const TileMath::TileKey& tile);
217 void _notifyCoveredMayHaveChanged(const TileMath::TileKey& changedKey);
218 void _scheduleStatsChanged();
219 void _startStatsSampling();
220 QImage _fallbackImage(const TileMath::TileKey& key) const;
221 QImage _compositeFromChildren(const TileMath::TileKey& key) const;
222 QImage _cropFromAncestor(const TileMath::TileKey& key) const;
223 bool _fallbackAvailable(const TileMath::TileKey& key) const;
224 GeoMapCamera* _camera() const;
225
226 static constexpr int kMaxRetiredImages = 128;
227 static constexpr int kMaxAncestorFallbackLevels = 8;
228 static constexpr int kImageRetryMs = 3000;
229 static constexpr double kSegmentSampleSpacingMeters = 30.0;
230 static constexpr int kMaxSegmentSamples = 2000;
231
232 GeoScene* _scene = nullptr;
233 HeightSource* _heightSource = nullptr;
234 HeightField* _heightField = nullptr;
235 SurfaceModel* _surfaceModel = nullptr;
236 bool _terrain = false;
237 bool _debugHills = false;
238 QString _mapType;
239 TileImageSource* _tileSource = nullptr;
240 QNetworkAccessManager* _tileImageNetworkManager = nullptr;
241 QHash<TileMath::TileKey, QImage> _tileImages;
245 mutable QHash<TileMath::TileKey, QImage> _fallbackCache;
246 QList<TileMath::TileKey> _retiredOrder;
247 QHash<int, TileMath::TileKey> _imageRequestKey;
248 QHash<TileMath::TileKey, int> _imageRequestByKey;
249 QSet<TileMath::TileKey> _failedImageKeys;
250 QTimer* _imageRetryTimer = nullptr;
251 QList<TileMath::TileKey> _keys;
252
253 // Perf counters sampled by _statsTick (see setStatsEnabled)
254 QTimer* _statsTimer = nullptr;
255 bool _statsEnabled = false;
256 bool _statsNotifyPending = false;
257 QString _statsText;
258 int _statAdds = 0;
259 int _statRemoves = 0;
260 mutable int _statComposites = 0;
261
262 // Capture recording (see startCapture)
263 bool _capturing = false;
264 QStringList _captureRows;
265 QElapsedTimer _captureClock;
266 double _captureWorstMaxMs = 0.0;
267 double _captureWorstAvgMs = 0.0;
268};
void terrainDataChanged()
terrainDataHeightAt / segmentBelowTerrain answers changed somewhere (not on patch churn)
void debugHillsChanged()
void statsEnabledChanged()
QString mapType() const
void terrainHeightsChanged()
terrainHeightAt answers changed somewhere: consumers re-query
HeightField * heightField() const
void setTileImageNetworkManager(QNetworkAccessManager *networkManager)
bool debugHills() const
@ SpanRole
patch edge length (m)
@ TileImageRole
drapable image: own tile, or ancestor/descendant fallback while loading
@ HasTileImageRole
QImage is opaque to QML; bool validity for bindings.
@ EdgeLodDeltasRole
{N,S,W,E} coarser-neighbor LOD deltas for edge stitching
@ ZoomRole
quadtree zoom level
@ TileYRole
slippy tile y of the patch key
@ CenterYRole
patch center y in scene meters
@ CoveredRole
pending but overlapped by a ready patch: delegate suppresses rendering
@ HeightsRole
vertex height grid (empty = flat)
@ TileXRole
slippy tile x of the patch key
int pendingImageCount() const
Tile image requests awaiting delivery or failure.
~SurfacePatchModel() override
GeoScene * scene() const
bool statsEnabled() const
QString statsText() const
int pendingCount() const
QString mapType() const