mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-04 00:45:46 +08:00
refs #296 implemented airportsInRange on XBus side
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include "blackmisc/geoearthangle.h"
|
#include "blackmisc/geoearthangle.h"
|
||||||
#include "blackmisc/geolatitude.h"
|
#include "blackmisc/geolatitude.h"
|
||||||
#include "blackmisc/geolongitude.h"
|
#include "blackmisc/geolongitude.h"
|
||||||
|
#include "blackmisc/geodesicgrid.h"
|
||||||
#include "blackmisc/coordinateecef.h"
|
#include "blackmisc/coordinateecef.h"
|
||||||
#include "blackmisc/coordinatened.h"
|
#include "blackmisc/coordinatened.h"
|
||||||
#include "blackmisc/coordinategeodetic.h"
|
#include "blackmisc/coordinategeodetic.h"
|
||||||
|
|||||||
177
src/blackmisc/geodesicgrid.h
Normal file
177
src/blackmisc/geodesicgrid.h
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef BLACKMISC_GEODESICGRID_H
|
||||||
|
#define BLACKMISC_GEODESICGRID_H
|
||||||
|
|
||||||
|
//! \file
|
||||||
|
|
||||||
|
#include "mathematics.h"
|
||||||
|
#include "coordinategeodetic.h"
|
||||||
|
#include "range.h"
|
||||||
|
#include "iterator.h"
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
namespace Geo
|
||||||
|
{
|
||||||
|
|
||||||
|
// Compute the integer log2(X) of an integer X at compile time
|
||||||
|
//! \private
|
||||||
|
template <typename T, T X, int Count = 0>
|
||||||
|
struct LogBase2 : std::conditional<bool (X >> 1),
|
||||||
|
LogBase2<T, (X >> 1), Count + 1>,
|
||||||
|
std::integral_constant<int, Count>>::type
|
||||||
|
{};
|
||||||
|
|
||||||
|
//! Associative container for efficiently storing and retreiving elements at points on the Earth's surface.
|
||||||
|
/*
|
||||||
|
We treat the Earth as a unit sphere, and convert latitude/longitude coordinates into x,y,z normal vectors.
|
||||||
|
The x axis points to 00N00W, the y axis points to 00N90E, the z axis points to the north pole.
|
||||||
|
|
||||||
|
We slice the Earth into N slices along lines of latitude (i.e. planes perpendicular to the z axis). Call these the z slices.
|
||||||
|
Then we further slice the Earth along planes perpendicular to the x axis and the y axis. Call these the x slices and the y slices.
|
||||||
|
Where an x slice, a y slice, and a z slice intersect on the sphere, there is a triangular tile of height 21600/2^N nautical miles.
|
||||||
|
*/
|
||||||
|
template <int Slices, class T, class Key = qint32>
|
||||||
|
class CGeodesicGrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Iterator
|
||||||
|
typedef typename QMultiMap<Key, T>::const_iterator const_iterator;
|
||||||
|
|
||||||
|
//! Begin and end iterators of the underlying storage.
|
||||||
|
//! @{
|
||||||
|
const_iterator begin() const { return m_map.begin(); }
|
||||||
|
const_iterator cbegin() const { return m_map.cbegin(); }
|
||||||
|
const_iterator end() const { return m_map.end(); }
|
||||||
|
const_iterator cend() const { return m_map.cend(); }
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! Removes all elements from all tiles.
|
||||||
|
void clear() { m_map.clear(); }
|
||||||
|
|
||||||
|
//! Returns true if there are no elements in any tiles.
|
||||||
|
bool isEmpty() const { return m_map.isEmpty(); }
|
||||||
|
|
||||||
|
//! Inserts an element in the tile at the given point.
|
||||||
|
//! \warning Angles are in radians.
|
||||||
|
void insert(double lat, double lon, const T &value) { m_map.insert(coordinateToKey(lat, lon), value); }
|
||||||
|
|
||||||
|
//! If T has latitude() and longitude() methods then this convenience insert() method can be used.
|
||||||
|
void insert(const T &value) { m_map.insert(value.latitude(), value.longitude(), value); }
|
||||||
|
|
||||||
|
//! Returns a range containing the elements in the tile at the given point.
|
||||||
|
//! \warning Angles are in radians.
|
||||||
|
CRange<const_iterator> inTileAt(double lat, double lon) const
|
||||||
|
{
|
||||||
|
Key k = coordinateToKey(lat, lon);
|
||||||
|
return makeRange(m_map.lowerBound(k), m_map.upperBound(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns a range containing the elements in every tile adjacent to the one at the given point, including that one.
|
||||||
|
//! \warning Angles are in radians.
|
||||||
|
CRange<Iterators::ConcatIterator<const_iterator>> inAdjacentTiles(double lat, double lon, int degree = 1) const
|
||||||
|
{
|
||||||
|
QVector<const_iterator> its;
|
||||||
|
for (auto k : adjacentKeys(coordinateToKey(lat, lon), degree))
|
||||||
|
{
|
||||||
|
its.push_back(m_map.lowerBound(k));
|
||||||
|
its.push_back(m_map.upperBound(k));
|
||||||
|
}
|
||||||
|
Q_ASSERT(!its.isEmpty());
|
||||||
|
return makeRange(Iterators::makeConcatIterator(its), its.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Overloaded method taking the coordinates in a different form.
|
||||||
|
//! @{
|
||||||
|
void insert(const CLatitude &lat, const CLongitude &lon, const T &value) { insert(lat.value(PhysicalQuantities::CAngleUnit::rad()), lon.value(PhysicalQuantities::CAngleUnit::rad()), value); }
|
||||||
|
void insert(const ICoordinateGeodetic &coord, const T &value) { insert(coord.latitude(), coord.longitude()); }
|
||||||
|
CRange<const_iterator> inTileAt(const CLatitude &lat, const CLongitude &lon) const { return inTileAt(lat.value(PhysicalQuantities::CAngleUnit::rad()), lon.value(PhysicalQuantities::CAngleUnit::rad())); }
|
||||||
|
CRange<const_iterator> inTileAt(const ICoordinateGeodetic &coord) const { return inTileAt(coord.latitude(), coord.longitude()); }
|
||||||
|
CRange<Iterators::ConcatIterator<const_iterator>> inAdjacentTiles(const CLatitude &lat, const CLongitude &lon, int degree = 1) const { return inAdjacentTiles(lat.value(PhysicalQuantities::CAngleUnit::rad()), lon.value(PhysicalQuantities::CAngleUnit::rad()), degree); }
|
||||||
|
CRange<Iterators::ConcatIterator<const_iterator>> inAdjacentTiles(const ICoordinateGeodetic &coord, int degree = 1) const { return inAdjacentTiles(coord.latitude(), coord.longitude(), degree); }
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! Returns the internal keys corresponding to all the tiles.
|
||||||
|
QList<Key> keys() const { return m_map.uniqueKeys(); }
|
||||||
|
|
||||||
|
//! Returns the number of elements in the tile corresponding to this internal key.
|
||||||
|
int count(Key k) const { return m_map.count(k); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMultiMap<Key, T> m_map;
|
||||||
|
|
||||||
|
static_assert(std::is_signed<Key>::value && std::is_integral<Key>::value, "Key must be a signed integer");
|
||||||
|
static_assert(Slices > 1 && !(Slices & (Slices - 1)), "Slices must be a power of two");
|
||||||
|
static_assert(LogBase2<Key, Slices>::value * 3 < sizeof(Key) * 8, "Key is too small to hold all Slices");
|
||||||
|
|
||||||
|
static const Key Zshift = 0;
|
||||||
|
static const Key Zmask = Slices - 1;
|
||||||
|
static const Key Zone = 1;
|
||||||
|
static const Key Yshift = LogBase2<Key, Slices>::value;
|
||||||
|
static const Key Ymask = Zmask << Yshift;
|
||||||
|
static const Key Yone = Zone << Yshift;
|
||||||
|
static const Key Xshift = Yshift * 2;
|
||||||
|
static const Key Xmask = Zmask << Xshift;
|
||||||
|
static const Key Xone = Zone << Xshift;
|
||||||
|
|
||||||
|
static Key coordinateToKey(double lat, double lon)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
using namespace BlackMisc::Math;
|
||||||
|
Q_ASSERT(lat >= -CMath::PIHALF() && lat <= CMath::PIHALF());
|
||||||
|
Q_ASSERT(lon >= -CMath::PI() && lon <= CMath::PI());
|
||||||
|
static const double ratio = Slices / CMath::PI();
|
||||||
|
Key x = qFloor(acos(cos(lat) * cos(lon)) * ratio);
|
||||||
|
Key y = qFloor(acos(cos(lat) * sin(lon)) * ratio);
|
||||||
|
Key z = qFloor( (lat + CMath::PIHALF()) * ratio);
|
||||||
|
return (x << Xshift) | (y << Yshift) | (z << Zshift);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QVector<Key> adjacentKeys(Key k, int d)
|
||||||
|
{
|
||||||
|
QVector<Key> adj;
|
||||||
|
for (int dx = -d; dx <= d; ++dx)
|
||||||
|
{
|
||||||
|
for (int dy = -d; dy <= d; ++dy)
|
||||||
|
{
|
||||||
|
for (int dz = -d; dz <= d; ++dz)
|
||||||
|
{
|
||||||
|
adj.push_back(plus(k, dx, dy, dz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return adj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Key plus(Key k, Key dx, Key dy, Key dz)
|
||||||
|
{
|
||||||
|
Key x = k & Xmask;
|
||||||
|
Key y = k & Ymask;
|
||||||
|
Key z = k & Zmask;
|
||||||
|
dx *= Xone;
|
||||||
|
dy *= Yone;
|
||||||
|
dz *= Zone;
|
||||||
|
if ((dx < 0 ? (-dx > x) : (dx > Xmask - x))
|
||||||
|
|| (dy < 0 ? (-dy > y) : (dy > Ymask - y))
|
||||||
|
|| (dz < 0 ? (-dz > z) : (dz > Zmask - z)))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (x + dx) | (y + dy) | (z + dz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // guard
|
||||||
|
|
||||||
@@ -204,6 +204,56 @@ namespace BlackMisc
|
|||||||
Optional<F> m_predicate;
|
Optional<F> m_predicate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Iterator wrapper which concatenates zero or more pairs of begin and end iterators.
|
||||||
|
*/
|
||||||
|
template <class I> class ConcatIterator : public std::iterator<std::input_iterator_tag, typename std::iterator_traits<I>::value_type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Constructor.
|
||||||
|
ConcatIterator(QVector<I> iterators) : m_iterators(std::move(iterators))
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_iterators.size() % 2 == 0);
|
||||||
|
while (!m_iterators.empty() && m_iterators[0] == m_iterators[1]) { m_iterators.remove(0, 2); }
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Implicit conversion from an end iterator.
|
||||||
|
ConcatIterator(I end) { Q_UNUSED(end); }
|
||||||
|
|
||||||
|
//! Advance to the next element.
|
||||||
|
//! Undefined if iterator is at the end.
|
||||||
|
//! @{
|
||||||
|
ConcatIterator &operator ++()
|
||||||
|
{
|
||||||
|
++(m_iterators[0]);
|
||||||
|
while (!m_iterators.empty() && m_iterators[0] == m_iterators[1]) { m_iterators.remove(0, 2); }
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ConcatIterator operator ++(int) { auto copy = *this; ++(*this); return copy; }
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! Indirection operator, returns the underlying iterator.
|
||||||
|
//! Undefined if iterator is at the end.
|
||||||
|
I operator ->() { return m_iterators[0]; }
|
||||||
|
|
||||||
|
//! Dereference operator, returns the object referenced by the iterator.
|
||||||
|
//! Undefined if iterator is at the end.
|
||||||
|
typename std::iterator_traits<I>::reference operator *() { return *(m_iterators[0]); }
|
||||||
|
|
||||||
|
//! Comparison operators.
|
||||||
|
//! @{
|
||||||
|
bool operator ==(const ConcatIterator &other) const { return m_iterators == other.m_iterators; }
|
||||||
|
bool operator !=(const ConcatIterator &other) const { return m_iterators != other.m_iterators; }
|
||||||
|
bool operator <(const ConcatIterator &other) const { return m_iterators < other.m_iterators; }
|
||||||
|
bool operator <=(const ConcatIterator &other) const { return m_iterators <= other.m_iterators; }
|
||||||
|
bool operator >(const ConcatIterator &other) const { return m_iterators > other.m_iterators; }
|
||||||
|
bool operator >=(const ConcatIterator &other) const { return m_iterators >= other.m_iterators; }
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<I> m_iterators;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a KeyIterator of the appropriate type from deduced template function argument.
|
* Construct a KeyIterator of the appropriate type from deduced template function argument.
|
||||||
*/
|
*/
|
||||||
@@ -228,6 +278,14 @@ namespace BlackMisc
|
|||||||
return { iterator, end, predicate };
|
return { iterator, end, predicate };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct a ConcatIterator of the appropriate type from deduced template function arguments.
|
||||||
|
*/
|
||||||
|
template <class I> auto makeConcatIterator(QVector<I> iterators) -> ConcatIterator<I>
|
||||||
|
{
|
||||||
|
return { std::move(iterators) };
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Generic type-erased const forward iterator with value semantics.
|
* \brief Generic type-erased const forward iterator with value semantics.
|
||||||
* \tparam T the value_type of the container being iterated over.
|
* \tparam T the value_type of the container being iterated over.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "traffic.h"
|
#include "traffic.h"
|
||||||
|
#include "service.h"
|
||||||
#include <XPLM/XPLMPlanes.h>
|
#include <XPLM/XPLMPlanes.h>
|
||||||
|
|
||||||
#if ! defined(XPLM210)
|
#if ! defined(XPLM210)
|
||||||
@@ -32,9 +33,13 @@ PLUGIN_API void XPluginStop()
|
|||||||
|
|
||||||
PLUGIN_API int XPluginEnable()
|
PLUGIN_API int XPluginEnable()
|
||||||
{
|
{
|
||||||
|
qRegisterMetaType<QDoubleList>();
|
||||||
|
qDBusRegisterMetaType<QDoubleList>();
|
||||||
|
|
||||||
QXPlaneMessageHandler::install();
|
QXPlaneMessageHandler::install();
|
||||||
g_qApp = QSharedApplication::sharedInstance();
|
g_qApp = QSharedApplication::sharedInstance();
|
||||||
QXPlaneEventLoop::exec();
|
QXPlaneEventLoop::exec();
|
||||||
|
|
||||||
g_plugin = new XBus::CPlugin;
|
g_plugin = new XBus::CPlugin;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -49,12 +54,19 @@ PLUGIN_API void XPluginReceiveMessage(XPLMPluginID from, long msg, void *param)
|
|||||||
{
|
{
|
||||||
if (from == XPLM_PLUGIN_XPLANE)
|
if (from == XPLM_PLUGIN_XPLANE)
|
||||||
{
|
{
|
||||||
if (msg == XPLM_MSG_PLANE_LOADED || msg == XPLM_MSG_LIVERY_LOADED)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
case XPLM_MSG_PLANE_LOADED:
|
||||||
|
case XPLM_MSG_LIVERY_LOADED:
|
||||||
if (reinterpret_cast<intptr_t>(param) == XPLM_USER_AIRCRAFT)
|
if (reinterpret_cast<intptr_t>(param) == XPLM_USER_AIRCRAFT)
|
||||||
{
|
{
|
||||||
g_plugin->onAircraftModelChanged();
|
g_plugin->onAircraftModelChanged();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XPLM_MSG_AIRPORT_LOADED:
|
||||||
|
g_plugin->onAircraftRepositioned();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,12 @@ namespace XBus
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlugin::onAircraftRepositioned()
|
||||||
|
{
|
||||||
|
if (m_service)
|
||||||
|
{
|
||||||
|
m_service->updateAirportsInRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ namespace XBus
|
|||||||
//! Called by XPluginReceiveMessage when the model is changed
|
//! Called by XPluginReceiveMessage when the model is changed
|
||||||
void onAircraftModelChanged();
|
void onAircraftModelChanged();
|
||||||
|
|
||||||
|
//! Called by XPluginReceiveMessage when the aircraft is positioned at an airport
|
||||||
|
void onAircraftRepositioned();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BlackCore::CDBusServer *m_server = nullptr;
|
BlackCore::CDBusServer *m_server = nullptr;
|
||||||
CService *m_service = nullptr;
|
CService *m_service = nullptr;
|
||||||
|
|||||||
@@ -6,12 +6,18 @@
|
|||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include <XPLM/XPLMPlanes.h>
|
#include <XPLM/XPLMPlanes.h>
|
||||||
#include <XPLM/XPLMUtilities.h>
|
#include <XPLM/XPLMUtilities.h>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
namespace XBus
|
namespace XBus
|
||||||
{
|
{
|
||||||
|
|
||||||
CService::CService(QObject *parent) : QObject(parent)
|
CService::CService(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
m_airportUpdater = new QTimer(this);
|
||||||
|
m_airportUpdater->start(60000);
|
||||||
|
connect(m_airportUpdater, &QTimer::timeout, this, &CService::updateAirportsInRange);
|
||||||
|
updateAirportsInRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CService::onAircraftModelChanged()
|
void CService::onAircraftModelChanged()
|
||||||
@@ -68,4 +74,60 @@ namespace XBus
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CService::readAirportsDatabase()
|
||||||
|
{
|
||||||
|
auto first = XPLMFindFirstNavAidOfType(xplm_Nav_Airport);
|
||||||
|
auto last = XPLMFindLastNavAidOfType(xplm_Nav_Airport);
|
||||||
|
if (first != XPLM_NAV_NOT_FOUND)
|
||||||
|
{
|
||||||
|
for (auto i = first; i <= last; ++i)
|
||||||
|
{
|
||||||
|
float lat, lon;
|
||||||
|
char icao[32];
|
||||||
|
XPLMGetNavAidInfo(i, nullptr, &lat, &lon, nullptr, nullptr, nullptr, icao, nullptr, nullptr);
|
||||||
|
if (icao[0] != 0)
|
||||||
|
{
|
||||||
|
using namespace BlackMisc::Math;
|
||||||
|
m_airports.insert(CMath::deg2rad(lat), CMath::deg2rad(lon), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int total = 0, count = 0, max = 0;
|
||||||
|
for (auto key : m_airports.keys())
|
||||||
|
{
|
||||||
|
qDebug() << "<><><><>" << QString("%1").arg(key, 6, 16, QChar('0')) << m_airports.count(key);
|
||||||
|
total += m_airports.count(key);
|
||||||
|
count++;
|
||||||
|
if (m_airports.count(key) > max) { max = m_airports.count(key); }
|
||||||
|
}
|
||||||
|
qDebug() << "<><><><> total" << total;
|
||||||
|
qDebug() << "<><><><> max" << max;
|
||||||
|
qDebug() << "<><><><> mean" << (total / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CService::updateAirportsInRange()
|
||||||
|
{
|
||||||
|
if (m_airports.isEmpty())
|
||||||
|
{
|
||||||
|
readAirportsDatabase();
|
||||||
|
}
|
||||||
|
using namespace BlackMisc::Math;
|
||||||
|
QStringList icaos, names;
|
||||||
|
QDoubleList lats, lons, alts;
|
||||||
|
for (auto navref : m_airports.inAdjacentTiles(CMath::deg2rad(getLatitude()), CMath::deg2rad(getLongitude())))
|
||||||
|
{
|
||||||
|
float lat, lon, alt;
|
||||||
|
char icao[32], name[256];
|
||||||
|
XPLMGetNavAidInfo(navref, nullptr, &lat, &lon, &alt, nullptr, nullptr, icao, name, nullptr);
|
||||||
|
icaos.push_back(icao);
|
||||||
|
names.push_back(name);
|
||||||
|
lats.push_back(lat);
|
||||||
|
lons.push_back(lon);
|
||||||
|
alts.push_back(alt);
|
||||||
|
}
|
||||||
|
qDebug() << alts;
|
||||||
|
emit airportsInRangeUpdated(icaos, names, lats, lons, alts);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,25 @@
|
|||||||
|
|
||||||
//! \file
|
//! \file
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
#include "datarefs.h"
|
#include "datarefs.h"
|
||||||
|
#include "blackmisc/geodesicgrid.h"
|
||||||
|
#include <XPLM/XPLMNavigation.h>
|
||||||
|
#include <QStringList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
//! \cond PRIVATE
|
//! \cond PRIVATE
|
||||||
#define XBUS_SERVICE_INTERFACENAME "net.vatsim.xbus.service"
|
#define XBUS_SERVICE_INTERFACENAME "net.vatsim.xbus.service"
|
||||||
#define XBUS_SERVICE_OBJECTPATH "/xbus"
|
#define XBUS_SERVICE_OBJECTPATH "/xbus"
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|
||||||
|
//! Typedef needed to use QList<double> as a DBus argument
|
||||||
|
typedef QList<double> QDoubleList;
|
||||||
|
Q_DECLARE_METATYPE(QDoubleList);
|
||||||
|
|
||||||
namespace XBus
|
namespace XBus
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -52,7 +63,13 @@ namespace XBus
|
|||||||
//! Emitted when the model or livery changes.
|
//! Emitted when the model or livery changes.
|
||||||
void aircraftModelChanged(const QString &path, const QString &filename, const QString &livery, const QString &icao);
|
void aircraftModelChanged(const QString &path, const QString &filename, const QString &livery, const QString &icao);
|
||||||
|
|
||||||
|
//! Airports in range updated.
|
||||||
|
void airportsInRangeUpdated(const QStringList &icaoCodes, const QStringList &names, const QDoubleList &lats, const QDoubleList &lons, const QDoubleList &alts);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
//! Called by newly connected client to cause airportsInRangeUpdated to be emitted.
|
||||||
|
void updateAirportsInRange();
|
||||||
|
|
||||||
//! Get full path to current aircraft model
|
//! Get full path to current aircraft model
|
||||||
QString getAircraftModelPath() const;
|
QString getAircraftModelPath() const;
|
||||||
|
|
||||||
@@ -153,6 +170,10 @@ namespace XBus
|
|||||||
void setTransponderMode(int mode) { m_xpdrMode.set(mode); }
|
void setTransponderMode(int mode) { m_xpdrMode.set(mode); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
BlackMisc::Geo::CGeodesicGrid<128, XPLMNavRef> m_airports;
|
||||||
|
QTimer *m_airportUpdater = nullptr;
|
||||||
|
void readAirportsDatabase();
|
||||||
|
|
||||||
StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath;
|
StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath;
|
||||||
StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao;
|
StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao;
|
||||||
DataRef<xplane::data::sim::flightmodel::position::latitude> m_latitude;
|
DataRef<xplane::data::sim::flightmodel::position::latitude> m_latitude;
|
||||||
|
|||||||
Reference in New Issue
Block a user