Enroute Flight Navigation
A navigation app for VFR pilots
GeoMapProvider.h
1/***************************************************************************
2 * Copyright (C) 2019-2024 by Stefan Kebekus *
3 * stefan.kebekus@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#pragma once
22
23#include <QCache>
24#include <QFuture>
25#include <QGeoRectangle>
26#include <QImage>
27#include <QProperty>
28#include <QQmlEngine>
29#include <QStandardPaths>
30#include <QTemporaryFile>
31#include <QTimer>
32
33#include "Airspace.h"
34#include "GlobalObject.h"
35#include "TileServer.h"
36#include "Waypoint.h"
37#include "fileFormats/MBTILES.h"
38
39using namespace Qt::Literals::StringLiterals;
40
41
42namespace GeoMaps
43{
44
63
65{
66 Q_OBJECT
67 QML_ELEMENT
68 QML_SINGLETON
69
70public:
77 explicit GeoMapProvider(QObject *parent = nullptr);
78
79 // No default constructor, important for QML singleton
80 explicit GeoMapProvider() = delete;
81
82 // deferred initialization
83 void deferredInitialization() override;
84
85 // factory function for QML singleton
86 static GeoMaps::GeoMapProvider* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/)
87 {
89 }
90
92 ~GeoMapProvider() override = default;
93
94
95
96 //
97 // Properties
98 //
99
104 Q_PROPERTY(QList<GeoMaps::Airspace> airspaces READ airspaces BINDABLE bindableAirspaces)
105
106
112
118 Q_PROPERTY(QString copyrightNotice READ copyrightNotice CONSTANT)
119
130
137
143 Q_PROPERTY(QByteArray geoJSON READ geoJSON BINDABLE bindableGeoJSON)
144
152 Q_PROPERTY(QString serverUrl READ serverUrl NOTIFY serverUrlChanged)
153
163 Q_PROPERTY(QString styleFileURL READ styleFileURL NOTIFY styleFileURLChanged)
164
166 Q_PROPERTY(QList<QSharedPointer<FileFormats::MBTILES>> terrainMapTiles READ terrainMapTiles NOTIFY terrainMapTilesChanged)
167
173 Q_PROPERTY(QList<GeoMaps::Waypoint> waypoints READ waypoints NOTIFY waypointsChanged)
174
175
176
177 //
178 // Getter Methods
179 //
180
185 [[nodiscard]] QList<GeoMaps::Airspace> airspaces() const {return m_airspaces.value();}
186
191 [[nodiscard]] QBindable<QList<GeoMaps::Airspace>> bindableAirspaces() {return &m_airspaces;}
192
197 [[nodiscard]] QStringList availableRasterMaps() const
198 {
199 return m_availableRasterMaps.value();
200 }
201
206 [[nodiscard]] QBindable<QStringList> bindableAvailableRasterMaps() const
207 {
208 return &m_availableRasterMaps;
209 }
210
215 [[nodiscard]] static QString copyrightNotice();
216
221 [[nodiscard]] QString currentRasterMap() const {return m_currentRasterMap.value();}
222
227 [[nodiscard]] QBindable<QString> bindableCurrentRasterMap() const {return &m_currentRasterMap;}
228
233 [[nodiscard]] int currentRasterMapTileSize() const {return m_currentRasterMapTileSize.value();}
234
239 [[nodiscard]] QBindable<int> bindableCurrentRasterMapTileSize() const {return &m_currentRasterMapTileSize;}
240
245 [[nodiscard]] QByteArray geoJSON() const {return m_combinedGeoJSON.value();}
246
251 [[nodiscard]] QBindable<QByteArray> bindableGeoJSON() {return &m_combinedGeoJSON;}
252
257 [[nodiscard]] QString serverUrl() {return m_tileServer.serverUrl();}
258
263 [[nodiscard]] QString styleFileURL();
264
269 [[nodiscard]] QList<QSharedPointer<FileFormats::MBTILES>> terrainMapTiles() const
270 {
271 return m_terrainMapTiles;
272 }
273
278 [[nodiscard]] QList<Waypoint> waypoints();
279
280
281
282 //
283 // Setter Methods
284 //
285
290 void setCurrentRasterMap(const QString& mapName);
291
292
293
294 //
295 // Methods
296 //
297
306 [[nodiscard]] Q_INVOKABLE QVariantList airspacesAtPosition(const QGeoCoordinate &position);
307
320 [[nodiscard]] Q_INVOKABLE GeoMaps::Waypoint closestWaypoint(QGeoCoordinate position, const QGeoCoordinate &distPosition);
321
329 [[nodiscard]] Q_INVOKABLE static GeoMaps::Waypoint createWaypoint()
330 {
331 return {};
332 }
333
341 [[nodiscard]] Q_INVOKABLE Units::Distance terrainElevationAMSL(const QGeoCoordinate& coordinate);
342
347 [[nodiscard]] Q_INVOKABLE static QByteArray emptyGeoJSON();
348
357 [[nodiscard]] Q_INVOKABLE QVector<GeoMaps::Waypoint> filteredWaypoints(const QString& filter);
358
365 [[nodiscard]] Q_INVOKABLE Waypoint findByID(const QString& icaoID);
366
377 [[nodiscard]] Q_INVOKABLE QList<GeoMaps::Waypoint> nearbyWaypoints(const QGeoCoordinate& position, const QString& type);
378
379
380signals:
383
386
389
392
395
396private:
397 Q_DISABLE_COPY_MOVE(GeoMapProvider)
398
399 // This slot is called every time the the set of aviation maps qchanges. It
400 // fills the aviation data cache.
401 void onAviationMapsChanged();
402
403 // This slot is called every time the the set of MBTile files changes. It
404 // sets up the tile server to and generates a new style file.
405 void onMBTILESChanged();
406
407 // Interal function that does most of the work for aviationMapsChanged()
408 // emits geoJSONChanged() when done. This function is meant to be run in a
409 // separate thread.
410 struct aviationDataCacheResult {
411 QList<Waypoint> waypoints;
412 QList<Airspace> airspaces;
413 QByteArray combinedGeoJSON;
414 };
415 aviationDataCacheResult fillAviationDataCache(QStringList JSONFileNames, Units::Distance airspaceAltitudeLimit, bool hideGlidingSectors);
416
417 // Caches used to speed up the method simplifySpecialChars
418 QRegularExpression specialChars{QStringLiteral("[^a-zA-Z0-9]")};
419 QHash<QString, QString> simplifySpecialChars_cache;
420
421 // This is the path under which map tiles are available on the m_tileServer.
422 // This is set to a random number that changes every time the set of MBTile
423 // files changes
424 QString _currentBaseMapPath;
425 QString _currentTerrainMapPath;
426
427 // Tile Server
428 TileServer m_tileServer;
429
430 // Temporary file that holds the current style file
431 QPointer<QTemporaryFile> m_styleFile;
432
433 //
434 // Aviation Data Cache
435 //
436 QFuture<GeoMaps::GeoMapProvider::aviationDataCacheResult> _aviationDataCacheFuture; // Future; indicates if fillAviationDataCache() is currently running
437 QTimer _aviationDataCacheTimer; // Timer used to start another run of fillAviationDataCache()
438
439 //
440 // MBTILES
441 //
442 QList<QSharedPointer<FileFormats::MBTILES>> m_baseMapVectorTiles;
443 QProperty<QList<QSharedPointer<FileFormats::MBTILES>>> m_baseMapRasterTiles;
444 QList<QSharedPointer<FileFormats::MBTILES>> m_terrainMapTiles;
445
446 QProperty<QStringList> m_availableRasterMaps;
447 QStringList computeAvailableRasterMaps();
448
449 QProperty<QString> m_currentRasterMap {u"non-empty place holder"_s};
450 QPropertyNotifier m_currentRasterMapNotifier; // Used to save the currentRasterMap
451 QProperty<int> m_currentRasterMapTileSize {512};
452
453 Q_OBJECT_BINDABLE_PROPERTY(GeoMaps::GeoMapProvider, QByteArray, m_combinedGeoJSON, &GeoMaps::GeoMapProvider::geoJSONChanged)
454 QList<Waypoint> _waypoints_; // Cache: Waypoints
455 QProperty<QList<Airspace>> m_airspaces; // Cache: Airspaces
456
457 // TerrainImageCache
458 QCache<qint64,QImage> terrainTileCache {6}; // Hold 6 tiles, roughly 1.2MB
459
460 // GeoJSON file
461 QString geoJSONCache {QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + u"/aviationData.json"_s};
462};
463
464} // namespace GeoMaps
A very simple class that describes an airspace.
Definition Airspace.h:33
Provides geographic information.
QBindable< QString > bindableCurrentRasterMap() const
Getter function for the property with the same name.
QList< Waypoint > waypoints()
Getter function for the property with the same name.
Q_INVOKABLE QList< GeoMaps::Waypoint > nearbyWaypoints(const QGeoCoordinate &position, const QString &type)
void terrainMapTilesChanged()
Notification signal for the property with the same name.
QBindable< QList< GeoMaps::Airspace > > bindableAirspaces()
Getter function for the property with the same name.
QBindable< QByteArray > bindableGeoJSON()
Getter function for the property with the same name.
QList< QSharedPointer< FileFormats::MBTILES > > terrainMapTiles() const
Getter function for the property with the same name.
QBindable< QStringList > bindableAvailableRasterMaps() const
Getter function for the property with the same name.
QString serverUrl()
Getter function for the property with the same name.
QStringList availableRasterMaps
Available Raster Maps.
Q_INVOKABLE Waypoint findByID(const QString &icaoID)
QString currentRasterMap
Current Raster Map.
QString currentRasterMap() const
Getter function for the property with the same name.
static Q_INVOKABLE GeoMaps::Waypoint createWaypoint()
Create invalid waypoint.
~GeoMapProvider() override=default
Destructor.
Q_INVOKABLE QVariantList airspacesAtPosition(const QGeoCoordinate &position)
List of airspaces at a given position.
Q_INVOKABLE QVector< GeoMaps::Waypoint > filteredWaypoints(const QString &filter)
Waypoints containing a given substring.
static Q_INVOKABLE QByteArray emptyGeoJSON()
Create empty GeoJSON document.
QByteArray geoJSON
Union of all aviation maps in GeoJSON format.
void styleFileURLChanged()
Notification signal for the property with the same name.
Q_INVOKABLE Units::Distance terrainElevationAMSL(const QGeoCoordinate &coordinate)
Elevation of terrain at a given coordinate, above sea level.
QString serverUrl
URL under which this server is presently reachable.
GeoMapProvider(QObject *parent=nullptr)
Creates a new GeoMap provider.
void geoJSONChanged()
Notification signal for the property with the same name.
QBindable< int > bindableCurrentRasterMapTileSize() const
Getter function for the property with the same name.
QString styleFileURL()
Getter function for the property with the same name.
QString copyrightNotice
Copyright notice for the map.
QList< GeoMaps::Airspace > airspaces
Available Airspaces.
QByteArray geoJSON() const
Getter function for the property with the same name.
QList< GeoMaps::Waypoint > waypoints
Waypoints.
void serverUrlChanged()
Notification signal for the property with the same name.
QStringList availableRasterMaps() const
Getter function for the property with the same name.
void deferredInitialization() override
Non-constructor initialization.
int currentRasterMapTileSize
Current Raster Map Tile Size.
int currentRasterMapTileSize() const
Getter function for the property with the same name.
void waypointsChanged()
Notification signal for the property with the same name.
QString styleFileURL
URL where a style file for the base map can be retrieved.
void setCurrentRasterMap(const QString &mapName)
Setter function for the property with the same name.
QListQSharedPointer< FileFormats::MBTILES > terrainMapTiles
List of terrain map MBTILES.
Q_INVOKABLE GeoMaps::Waypoint closestWaypoint(QGeoCoordinate position, const QGeoCoordinate &distPosition)
Find closest waypoint to a given position.
static QString copyrightNotice()
Getter function for the property with the same name.
Waypoint, such as an airfield, a navaid station or a reporting point.
Definition Waypoint.h:41
static Q_INVOKABLE GeoMaps::GeoMapProvider * geoMapProvider()
Pointer to appplication-wide static GeoMaps::GeoMapProvider instance.
GlobalObject(QObject *parent=nullptr)
Standard constructor.
Convenience class for distance computations.
Definition Distance.h:35