From c03d45123d9b3123e12ad06022260e949281e13b Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 1 Jul 2014 13:39:16 +0200 Subject: [PATCH] refs #291, airport class, list --- src/blackmisc/avairport.cpp | 208 ++++++++++++++++++++++++++++++++ src/blackmisc/avairport.h | 151 +++++++++++++++++++++++ src/blackmisc/avairportlist.cpp | 110 +++++++++++++++++ src/blackmisc/avairportlist.h | 65 ++++++++++ src/blackmisc/avallclasses.h | 2 + 5 files changed, 536 insertions(+) create mode 100644 src/blackmisc/avairport.cpp create mode 100644 src/blackmisc/avairport.h create mode 100644 src/blackmisc/avairportlist.cpp create mode 100644 src/blackmisc/avairportlist.h diff --git a/src/blackmisc/avairport.cpp b/src/blackmisc/avairport.cpp new file mode 100644 index 000000000..d6909690b --- /dev/null +++ b/src/blackmisc/avairport.cpp @@ -0,0 +1,208 @@ +#include "avairport.h" +#include "blackmiscfreefunctions.h" + +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; + +namespace BlackMisc +{ + namespace Aviation + { + + /* + * Constructor + */ + CAirport::CAirport() : + m_distanceToPlane(0, CLengthUnit::nullUnit()) + { } + + /* + * Constructor + */ + CAirport::CAirport(const QString &icao) : + m_icao(icao), m_distanceToPlane(0, CLengthUnit::nullUnit()) + { } + + /* + * Constructor + */ + CAirport::CAirport(const CAirportIcao &icao, const BlackMisc::Geo::CCoordinateGeodetic &position) : + m_icao(icao), m_position(position), m_distanceToPlane(0, CLengthUnit::nullUnit()) + { } + + /* + * Convert to string + */ + QString CAirport::convertToQString(bool i18n) const + { + QString s = i18n ? + QCoreApplication::translate("Aviation", "Airport") : + "Airport"; + if (!this->m_icao.isEmpty()) + s.append(' ').append(this->m_icao.toQString(i18n)); + + // position + s.append(' ').append(this->m_position.toQString(i18n)); + return s; + + // force strings for translation in resource files + (void)QT_TRANSLATE_NOOP("Aviation", "ATC station"); + } + + /* + * Register metadata + */ + void CAirport::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Members + */ + const QStringList &CAirport::jsonMembers() + { + return TupleConverter::jsonMembers(); + } + + /* + * To JSON + */ + QJsonObject CAirport::toJson() const + { + return BlackMisc::serializeJson(CAirport::jsonMembers(), TupleConverter::toTuple(*this)); + } + + /* + * From Json + */ + void CAirport::fromJson(const QJsonObject &json) + { + BlackMisc::deserializeJson(json, CAirport::jsonMembers(), TupleConverter::toTuple(*this)); + } + + /* + * Compare + */ + int CAirport::compareImpl(const CValueObject &otherBase) const + { + const auto &other = static_cast(otherBase); + return compare(TupleConverter::toTuple(*this), TupleConverter::toTuple(other)); + } + + /* + * Marshall to DBus + */ + void CAirport::marshallToDbus(QDBusArgument &argument) const + { + argument << TupleConverter::toTuple(*this); + } + + /* + * Unmarshall from DBus + */ + void CAirport::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> TupleConverter::toTuple(*this); + } + + /* + * Equal? + */ + bool CAirport::operator ==(const CAirport &other) const + { + if (this == &other) return true; + return TupleConverter::toTuple(*this) == TupleConverter::toTuple(other); + } + + /* + * Hash + */ + uint CAirport::getValueHash() const + { + return qHash(TupleConverter::toTuple(*this)); + } + + /* + * Unequal? + */ + bool CAirport::operator !=(const CAirport &other) const + { + return !((*this) == other); + } + + /* + * Distance to planne + */ + const CLength &CAirport::calculcateDistanceToPlane(const CCoordinateGeodetic &position) + { + this->m_distanceToPlane = Geo::greatCircleDistance(this->m_position, position); + return this->m_distanceToPlane; + } + + /* + * Property by index + */ + QVariant CAirport::propertyByIndex(int index) const + { + switch (index) + { + case IndexIcao: + return this->m_icao.toQVariant(); + case IndexIcaoAsString: + return QVariant(this->m_icao.asString()); + case IndexPosition: + return this->getPosition().toQVariant(); + case IndexDistanceToPlane: + return this->m_distanceToPlane.toQVariant(); + default: + break; + } + + Q_ASSERT_X(false, "CAirport", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Set property as index + */ + void CAirport::setPropertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexIcao: + this->setIcao(variant.value()); + break; + case IndexIcaoAsString: + this->setIcao(CAirportIcao(variant.toString())); + break; + case IndexPosition: + this->setPosition(variant.value()); + break; + default: + Q_ASSERT_X(false, "CAirport", "index unknown (setter)"); + break; + } + } + + /* + * metaTypeId + */ + int CAirport::getMetaTypeId() const + { + return qMetaTypeId(); + } + + /* + * is a + */ + bool CAirport::isA(int metaTypeId) const + { + if (metaTypeId == qMetaTypeId()) { return true; } + return this->CValueObject::isA(metaTypeId); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avairport.h b/src/blackmisc/avairport.h new file mode 100644 index 000000000..935a1ba81 --- /dev/null +++ b/src/blackmisc/avairport.h @@ -0,0 +1,151 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * 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/. */ + +//! \file + +#ifndef BLACKMISC_AIRPORT_H +#define BLACKMISC_AIRPORT_H + +#include "avairporticao.h" +#include "coordinategeodetic.h" + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information about an airpot. + */ + class CAirport : public BlackMisc::CValueObject, public BlackMisc::Geo::ICoordinateGeodetic + { + + public: + //! Properties by index + enum ColumnIndex + { + IndexIcao = 0, + IndexIcaoAsString, + IndexPosition, + IndexDistanceToPlane + }; + + //! Default constructor. + CAirport(); + + //! Simplified constructor + CAirport(const QString &icao); + + //! ATC station constructor + CAirport(const CAirportIcao &icao, const BlackMisc::Geo::CCoordinateGeodetic &position); + + //! \copydoc CValueObject::toQVariant() + virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); } + + //! Equal operator == + bool operator ==(const CAirport &other) const; + + //! Unequal operator != + bool operator !=(const CAirport &other) const; + + //! Get ICAO code. + const CAirportIcao &getIcao() const { return m_icao; } + + //! Set ICAO code. + void setIcao(const CAirportIcao &icao) { m_icao = icao; } + + //! Get ICAO code as string. + QString getIcaoAsString() const { return m_icao.asString(); } + + //! Get the position + const BlackMisc::Geo::CCoordinateGeodetic &getPosition() const { return m_position; } + + //! Set position + void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_position = position; } + + //! Get the distance to own plane + const BlackMisc::PhysicalQuantities::CLength &getDistanceToPlane() const { return m_distanceToPlane; } + + //! Set distance to own plane + void setDistanceToPlane(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToPlane = distance; } + + //! Valid distance? + bool hasValidDistance() const { return !this->m_distanceToPlane.isNull();} + + //! Valid ICAO code + bool hasValidIcaoCode() const { return !this->getIcao().isEmpty(); } + + /*! + * Calculcate distance to plane, set it, and also return it + * \param position other position + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &calculcateDistanceToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); + + //! \copydoc ICoordinateGeodetic::latitude + virtual const BlackMisc::Geo::CLatitude &latitude() const override + { + return this->getPosition().latitude(); + } + + //! \copydoc ICoordinateGeodetic::longitude + virtual const BlackMisc::Geo::CLongitude &longitude() const override + { + return this->getPosition().longitude(); + } + + //! \copydoc CValueObject::getValueHash() + virtual uint getValueHash() const override; + + //! \copydoc CValueObject::propertyByIndex() + virtual QVariant propertyByIndex(int index) const override; + + //! \copydoc CValueObject::setPropertyByIndex(variant, index) + virtual void setPropertyByIndex(const QVariant &variant, int index) override; + + //! \copydoc CValueObject::toJson + virtual QJsonObject toJson() const override; + + //! \copydoc CValueObject::fromJson + void fromJson(const QJsonObject &json) override; + + //! Register metadata + static void registerMetadata(); + + //! \copydoc TupleConverter<>::jsonMembers() + static const QStringList &jsonMembers(); + + protected: + //! \copydoc CValueObject::convertToQString + virtual QString convertToQString(bool i18n = false) const override; + + //! \copydoc CValueObject::getMetaTypeId + virtual int getMetaTypeId() const override; + + //! \copydoc CValueObject::isA + virtual bool isA(int metaTypeId) const override; + + //! \copydoc CValueObject::compareImpl + virtual int compareImpl(const CValueObject &other) const override; + + //! \copydoc CValueObject::marshallToDbus() + virtual void marshallToDbus(QDBusArgument &argument) const override; + + //! \copydoc CValueObject::unmarshallFromDbus() + virtual void unmarshallFromDbus(const QDBusArgument &argument) override; + + private: + BLACK_ENABLE_TUPLE_CONVERSION(CAirport) + CAirportIcao m_icao; + BlackMisc::Geo::CCoordinateGeodetic m_position; + BlackMisc::PhysicalQuantities::CLength m_distanceToPlane; + }; + + } // namespace +} // namespace + +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirport, (o.m_icao, o.m_position)) +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirport) + +#endif // guard diff --git a/src/blackmisc/avairportlist.cpp b/src/blackmisc/avairportlist.cpp new file mode 100644 index 000000000..d8d95d20a --- /dev/null +++ b/src/blackmisc/avairportlist.cpp @@ -0,0 +1,110 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * 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/. */ + +#include "avairportlist.h" +#include "predicates.h" + +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Empty constructor + */ + CAirportList::CAirportList() { } + + /* + * Construct from base class object + */ + CAirportList::CAirportList(const CSequence &other) : + CSequence(other) + { } + + /* + * Register metadata + */ + void CAirportList::registerMetadata() + { + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Find by ICAO + */ + CAirportList CAirportList::findByIcao(const CAirportIcao &icao) const + { + return this->findBy(&CAirport::getIcao, icao); + } + + void CAirportList::replaceOrAddByIcao(const CAirport &addedOrReplacedAirport) + { + Q_ASSERT(addedOrReplacedAirport.hasValidIcaoCode()); + this->replaceOrAdd(&CAirport::getIcao, addedOrReplacedAirport.getIcao(), addedOrReplacedAirport); + } + + /* + * Find first by ICAO + */ + CAirport CAirportList::findFirstByIcao(const CAirportIcao &icao, const CAirport &ifNotFound) const + { + CAirportList airports = this->findByIcao(icao); + if (!airports.isEmpty()) return airports[0]; + return ifNotFound; + } + + /* + * airports within range + */ + CAirportList CAirportList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const + { + return this->findBy([&](const CAirport & atcairport) + { + return greatCircleDistance(atcairport, coordinate) <= range; + }); + } + + /* + * Distances to own plane + */ + void CAirportList::calculateDistancesToPlane(const Geo::CCoordinateGeodetic &position) + { + std::for_each(this->begin(), this->end(), [ & ](CAirport & airport) + { + airport.calculcateDistanceToPlane(position); + }); + } + + void CAirportList::removeIfOutsideRange(const Geo::CCoordinateGeodetic &position, const CLength &distance, bool updateDistance) + { + CLength d; + for (CAirportList::iterator i = begin(); i != end();) + { + if (updateDistance) + { + d = i->calculcateDistanceToPlane(position); + } + else + { + d = i->greatCircleDistance(position); + } + if (distance > d) + { + i = this->erase(i); + } + else + { + ++i; + } + } + } + } // namespace +} // namespace diff --git a/src/blackmisc/avairportlist.h b/src/blackmisc/avairportlist.h new file mode 100644 index 000000000..89a56d3e1 --- /dev/null +++ b/src/blackmisc/avairportlist.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * 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/. */ + +//! \file + +#ifndef BLACKMISC_AIRPORTLIST_H +#define BLACKMISC_AIRPORTLIST_H + +#include "avairport.h" +#include "collection.h" +#include "sequence.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object for a list of airports. + */ + class CAirportList : public CSequence + { + public: + //! Default constructor. + CAirportList(); + + //! Construct from a base class object. + CAirportList(const CSequence &other); + + //! \copydoc CValueObject::toQVariant() + virtual QVariant toQVariant() const { return QVariant::fromValue(*this); } + + //! Find 0..n airports by ICAO code + CAirportList findByIcao(const CAirportIcao &icao) const; + + //! Replace or add based on same ICAO code + void replaceOrAddByIcao(const CAirport &addedOrReplacedAirport); + + //! Find first station by callsign, if not return given value / default + CAirport findFirstByIcao(const CAirportIcao &icao, const CAirport &ifNotFound = CAirport()) const; + + //! Find 0..n airports within range of given coordinate + CAirportList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; + + //! Update distances to coordinate, usually own aircraft's position + void calculateDistancesToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); + + //! Remove if outside given radius + void removeIfOutsideRange(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &distance, bool updateDistance); + + //! Register metadata + static void registerMetadata(); + }; + } //namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirportList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/avallclasses.h b/src/blackmisc/avallclasses.h index 6a57bb5f1..72fb8f897 100644 --- a/src/blackmisc/avallclasses.h +++ b/src/blackmisc/avallclasses.h @@ -19,6 +19,8 @@ #include "blackmisc/avatcstationlist.h" #include "blackmisc/avaircraft.h" #include "blackmisc/avaircraftlist.h" +#include "blackmisc/avairport.h" +#include "blackmisc/avairportlist.h" #include "blackmisc/avinformationmessage.h" #include "blackmisc/avselcal.h" #include "blackmisc/avflightplan.h"