From ce86c902b56a96878b7f99be9c630559067f48db Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 27 Jan 2015 03:27:01 +0100 Subject: [PATCH] Upfront of refs #369 * consolidated ICoordinateGeodetic (e.g. fixed nested properties) * shifted common functionality for objects/containers with callsign into interface * shifted common functionality for objects/containers with geo position into interface * shifted common functionality for objects/containers with timestamp into interface * updated corresponding value objects / specialized lists * adjusted all places where renamed functions are used --- samples/blackmiscvectorgeo/samplesgeo.cpp | 4 +- src/blackcore/airspace_monitor.cpp | 10 +- src/blackcore/interpolator.h | 18 ++- src/blackcore/interpolator_linear.cpp | 34 +++-- src/blackcore/interpolator_linear.h | 16 ++- src/blackgui/models/aircraftlistmodel.cpp | 4 +- src/blackgui/models/airportlistmodel.cpp | 4 +- src/blackgui/models/atcstationlistmodel.cpp | 6 +- .../models/simulatedaircraftlistmodel.cpp | 6 +- src/blackmisc/avaircraft.cpp | 67 ++------- src/blackmisc/avaircraft.h | 40 ++---- src/blackmisc/avaircraftlist.cpp | 52 ------- src/blackmisc/avaircraftlist.h | 39 ++---- src/blackmisc/avaircraftsituation.cpp | 16 ++- src/blackmisc/avaircraftsituation.h | 62 +++++--- src/blackmisc/avaircraftsituationlist.cpp | 52 ++----- src/blackmisc/avaircraftsituationlist.h | 51 +++---- src/blackmisc/avairport.cpp | 32 ++--- src/blackmisc/avairport.h | 40 ++---- src/blackmisc/avairportlist.cpp | 45 ------ src/blackmisc/avairportlist.h | 44 +++--- src/blackmisc/avatcstation.cpp | 55 +++++--- src/blackmisc/avatcstation.h | 39 ++---- src/blackmisc/avatcstationlist.cpp | 98 ++----------- src/blackmisc/avatcstationlist.h | 46 +++--- src/blackmisc/avcallsignobjectlist.cpp | 130 +++++++++++++++++ src/blackmisc/avcallsignobjectlist.h | 74 ++++++++++ src/blackmisc/coordinategeodetic.cpp | 110 +++++++-------- src/blackmisc/coordinategeodetic.h | 115 +++++++++------ src/blackmisc/geoobjectlist.cpp | 83 +++++++++++ src/blackmisc/geoobjectlist.h | 71 ++++++++++ src/blackmisc/propertyindex.h | 1 + .../simulation/simulatedaircraftlist.cpp | 69 --------- .../simulation/simulatedaircraftlist.h | 39 ++---- src/blackmisc/testing.cpp | 10 +- src/blackmisc/timestampbased.cpp | 117 ++++++++++++++++ src/blackmisc/timestampbased.h | 95 +++++++++++++ src/blackmisc/timestampobjectlist.cpp | 132 ++++++++++++++++++ src/blackmisc/timestampobjectlist.h | 78 +++++++++++ .../fs9/blacksimplugin_freefunctions.cpp | 4 +- .../fsx/simulator_fsx_simconnectproc.cpp | 2 +- .../simulator/xplane/simulator_xplane.cpp | 5 +- .../simulator/xplane/simulator_xplane.h | 1 + tests/blackcore/testinterpolator.cpp | 29 ++-- tests/blackmisc/testvariantandmap.cpp | 2 +- 45 files changed, 1257 insertions(+), 790 deletions(-) create mode 100644 src/blackmisc/avcallsignobjectlist.cpp create mode 100644 src/blackmisc/avcallsignobjectlist.h create mode 100644 src/blackmisc/geoobjectlist.cpp create mode 100644 src/blackmisc/geoobjectlist.h create mode 100644 src/blackmisc/timestampbased.cpp create mode 100644 src/blackmisc/timestampbased.h create mode 100644 src/blackmisc/timestampobjectlist.cpp create mode 100644 src/blackmisc/timestampobjectlist.h diff --git a/samples/blackmiscvectorgeo/samplesgeo.cpp b/samples/blackmiscvectorgeo/samplesgeo.cpp index 1dd42b276..24c944833 100644 --- a/samples/blackmiscvectorgeo/samplesgeo.cpp +++ b/samples/blackmiscvectorgeo/samplesgeo.cpp @@ -48,8 +48,8 @@ namespace BlackMiscTest CCoordinateGeodetic coord1 = CCoordinateGeodetic::fromWgs84("50 03 59N", "005 42 53W"); CCoordinateGeodetic coord2 = CCoordinateGeodetic::fromWgs84("50 03 59N", "005 42 53W"); CCoordinateGeodetic coord3 = CCoordinateGeodetic::fromWgs84("58 38 38N", "003 04 12W"); - qDebug() << coord1 << coord2 << greatCircleDistance(coord1, coord2); // should be 0 - qDebug() << coord1 << coord3 << greatCircleDistance(coord1, coord3) << greatCircleDistance(coord1, coord3).switchUnit(CLengthUnit::km()) ; // should be Distance: 968.9 km (to 4 SF*) + qDebug() << coord1 << coord2 << calculateGreatCircleDistance(coord1, coord2); // should be 0 + qDebug() << coord1 << coord3 << calculateGreatCircleDistance(coord1, coord3) << calculateGreatCircleDistance(coord1, coord3).switchUnit(CLengthUnit::km()) ; // should be Distance: 968.9 km (to 4 SF*) // bye qDebug() << "-----------------------------------------------"; diff --git a/src/blackcore/airspace_monitor.cpp b/src/blackcore/airspace_monitor.cpp index f673b10d6..6e6eae1d8 100644 --- a/src/blackcore/airspace_monitor.cpp +++ b/src/blackcore/airspace_monitor.cpp @@ -203,7 +203,7 @@ namespace BlackCore CAtcStationList stations = this->m_atcStationsOnline.findIfComUnitTunedIn25KHz(comSystem); if (!stations.isEmpty()) { - stations.sortBy(&CAtcStation::getDistanceToPlane); + stations.sortBy(&CAtcStation::getDistanceToOwnAircraft); station = stations.front(); } return station; @@ -488,7 +488,7 @@ namespace BlackCore station.setFrequency(frequency); station.setPosition(position); station.setOnline(true); - station.calculcateDistanceToPlane(this->m_ownAircraft.getPosition()); + station.calculcateDistanceAndBearingToOwnAircraft(this->m_ownAircraft.getPosition()); this->m_vatsimDataFileReader->getAtcStations().updateFromVatsimDataFileStation(station); // prefill this->m_atcStationsOnline.push_back(station); @@ -634,7 +634,7 @@ namespace BlackCore aircraft.setCallsign(callsign); aircraft.setSituation(situation); aircraft.setTransponder(transponder); - aircraft.setCalculcatedDistanceToPosition(this->m_ownAircraft.getPosition()); // distance from myself + aircraft.calculcateDistanceAndBearingToOwnAircraft(this->m_ownAircraft.getPosition()); // distance from myself // ICAO from cache if avialable bool setIcao = false; @@ -683,12 +683,12 @@ namespace BlackCore else // not exists yet { // update - CLength distance = this->m_ownAircraft.calculcateDistanceToPosition(situation.getPosition()); + CLength distance = this->m_ownAircraft.calculateGreatCircleDistance(situation.getPosition()); distance.switchUnit(CLengthUnit::NM()); CPropertyIndexVariantMap vm; vm.addValue(CAircraft::IndexTransponder, transponder); vm.addValue(CAircraft::IndexSituation, situation); - vm.addValue(CAircraft::IndexDistance, distance); + vm.addValue(CAircraft::IndexDistanceToOwnAircraft, distance); // here I expect always a changed value this->m_aircraftInRange.applyIfCallsign(callsign, vm); diff --git a/src/blackcore/interpolator.h b/src/blackcore/interpolator.h index 48c27e97d..496e2bfb4 100644 --- a/src/blackcore/interpolator.h +++ b/src/blackcore/interpolator.h @@ -1,7 +1,13 @@ -/* 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/. */ +/* Copyright (C) 2014 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file #ifndef BLACKCORE_INTERPOLATOR_H #define BLACKCORE_INTERPOLATOR_H @@ -34,9 +40,9 @@ namespace BlackCore virtual BlackMisc::Aviation::CAircraftSituation getCurrentSituation() = 0; //! Get timestamp of the last received aircraft situation - virtual const QDateTime &getTimeOfLastReceivedSituation() const = 0; + virtual QDateTime getTimeOfLastReceivedSituation() const = 0; }; -} // namespace BlackCore +} // namespace #endif // guard diff --git a/src/blackcore/interpolator_linear.cpp b/src/blackcore/interpolator_linear.cpp index 12bc8e441..3a5511209 100644 --- a/src/blackcore/interpolator_linear.cpp +++ b/src/blackcore/interpolator_linear.cpp @@ -1,7 +1,11 @@ -/* 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/. */ +/* Copyright (C) 2014 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ #include "interpolator_linear.h" #include "blackmisc/avaircraftsituation.h" @@ -61,25 +65,25 @@ namespace BlackCore CCoordinateGeodetic currentPosition; // Time between start and end packet - double deltaTime = beginSituation.getTimestamp().msecsTo(endSituation.getTimestamp()); + double deltaTime = beginSituation.msecsToAbs(endSituation); // Fraction of the deltaTime [0.0 - 1.0] - double simulationTime = beginSituation.getTimestamp().msecsTo(currentTime) / deltaTime; + double simulationTimeFraction = beginSituation.getUtcTimestamp().msecsTo(currentTime) / deltaTime; // Interpolate latitude: Lat = (LatB - LatA) * t + LatA currentPosition.setLatitude((endSituation.getPosition().latitude() - beginSituation.getPosition().latitude()) - * simulationTime + * simulationTimeFraction + beginSituation.getPosition().latitude()); // Interpolate latitude: Lon = (LonB - LonA) * t + LonA currentPosition.setLongitude((endSituation.getPosition().longitude() - beginSituation.getPosition().longitude()) - * simulationTime + * simulationTimeFraction + beginSituation.getPosition().longitude()); currentSituation.setPosition(currentPosition); // Interpolate altitude: Alt = (AltB - AltA) * t + AltA currentSituation.setAltitude(CAltitude((endSituation.getAltitude() - beginSituation.getAltitude()) - * simulationTime + * simulationTimeFraction + beginSituation.getAltitude(), beginSituation.getAltitude().getReferenceDatum())); @@ -94,7 +98,7 @@ namespace BlackCore headingEnd -= CHeading(360, CHeading::Magnetic, CAngleUnit::deg()); currentSituation.setHeading(CHeading((headingEnd - headingBegin) - * simulationTime + * simulationTimeFraction + headingBegin, headingBegin.getReferenceNorth())); @@ -102,7 +106,7 @@ namespace BlackCore CAngle pitchBegin = beginSituation.getPitch(); CAngle pitchEnd = endSituation.getPitch(); - CAngle pitch = (pitchEnd - pitchBegin) * simulationTime + pitchBegin; + CAngle pitch = (pitchEnd - pitchBegin) * simulationTimeFraction + pitchBegin; // TODO: According to the specification, pitch above horizon should be negative. // But somehow we get positive pitches from the network. @@ -113,7 +117,7 @@ namespace BlackCore CAngle bankBegin = beginSituation.getBank(); CAngle bankEnd = endSituation.getBank(); - CAngle bank = (bankEnd - bankBegin) * simulationTime + bankBegin; + CAngle bank = (bankEnd - bankBegin) * simulationTimeFraction + bankBegin; // TODO: According to the specification, banks to the right should be negative. // But somehow we get positive banks from the network. @@ -121,14 +125,14 @@ namespace BlackCore currentSituation.setBank(bank); currentSituation.setGroundspeed((endSituation.getGroundSpeed() - beginSituation.getGroundSpeed()) - * simulationTime + * simulationTimeFraction + beginSituation.getGroundSpeed()); return currentSituation; } - const QDateTime &CInterpolatorLinear::getTimeOfLastReceivedSituation() const + QDateTime CInterpolatorLinear::getTimeOfLastReceivedSituation() const { - return m_aircraftSituationList.back().getTimestamp(); + return m_aircraftSituationList.back().getUtcTimestamp(); } } diff --git a/src/blackcore/interpolator_linear.h b/src/blackcore/interpolator_linear.h index 9e79fbdbd..f58b37242 100644 --- a/src/blackcore/interpolator_linear.h +++ b/src/blackcore/interpolator_linear.h @@ -1,7 +1,13 @@ -/* 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/. */ +/* Copyright (C) 2014 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file #ifndef BLACKCORE_INTERPOLATOR_LINEAR_H #define BLACKCORE_INTERPOLATOR_LINEAR_H @@ -37,7 +43,7 @@ namespace BlackCore virtual BlackMisc::Aviation::CAircraftSituation getCurrentSituation() override; //! \copydoc IInterpolator::getTimeOfLastReceivedSituation() - virtual const QDateTime &getTimeOfLastReceivedSituation() const override; + virtual QDateTime getTimeOfLastReceivedSituation() const override; private: BlackMisc::Aviation::CAircraftSituationList m_aircraftSituationList; diff --git a/src/blackgui/models/aircraftlistmodel.cpp b/src/blackgui/models/aircraftlistmodel.cpp index 65eb963ff..307a3e790 100644 --- a/src/blackgui/models/aircraftlistmodel.cpp +++ b/src/blackgui/models/aircraftlistmodel.cpp @@ -26,7 +26,7 @@ namespace BlackGui { this->m_columns.addColumn(CColumn::standardValueObject("cs.", "callsign", { CAircraft::IndexCallsign, CCallsign::IndexCallsignString })); this->m_columns.addColumn(CColumn::standardString("realname", "pilot's real name", { CAircraft::IndexPilot, CUser::IndexRealName })); - this->m_columns.addColumn(CColumn("distance", CAircraft::IndexDistance, new CAirspaceDistanceFormatter())); + this->m_columns.addColumn(CColumn("distance", CAircraft::IndexDistanceToOwnAircraft, new CAirspaceDistanceFormatter())); this->m_columns.addColumn(CColumn("frequency", { CAircraft::IndexCom1System, CComSystem::IndexActiveFrequency }, new CComFrequencyFormatter())); this->m_columns.addColumn(CColumn::standardString("icao", { CAircraft::IndexIcao, CAircraftIcao::IndexAsString})); this->m_columns.addColumn(CColumn::standardString("transponder", { CAircraft::IndexTransponder, CTransponder::IndexTransponderCodeAndModeFormatted })); @@ -36,7 +36,7 @@ namespace BlackGui this->m_columns.addColumn(CColumn("gs", { CAircraft::IndexSituation, CAircraftSituation::IndexGroundspeed }, new CAircraftSpeedFormatter())); // default sort order - this->setSortColumnByPropertyIndex(CAircraft::IndexDistance); + this->setSortColumnByPropertyIndex(CAircraft::IndexDistanceToOwnAircraft); this->m_sortOrder = Qt::AscendingOrder; // force strings for translation in resource files diff --git a/src/blackgui/models/airportlistmodel.cpp b/src/blackgui/models/airportlistmodel.cpp index 46bb8f036..5111531ad 100644 --- a/src/blackgui/models/airportlistmodel.cpp +++ b/src/blackgui/models/airportlistmodel.cpp @@ -27,7 +27,7 @@ namespace BlackGui CListModelBase("ViewAirportList", parent) { this->m_columns.addColumn(CColumn::standardValueObject("ICAO", CAirport::IndexIcao)); - this->m_columns.addColumn(CColumn("distance", CAirport::IndexDistance, new CAirspaceDistanceFormatter())); + this->m_columns.addColumn(CColumn("distance", CAirport::IndexDistanceToOwnAircraft, new CAirspaceDistanceFormatter())); this->m_columns.addColumn(CColumn("bearing", CAirport::IndexBearing, new CAngleDegreeFormatter())); this->m_columns.addColumn(CColumn::standardString("name", CAirport::IndexDescriptiveName)); this->m_columns.addColumn(CColumn("elevation", CAirport::IndexElevation, new CPhysiqalQuantiyFormatter(CLengthUnit::ft(), 0))); @@ -35,7 +35,7 @@ namespace BlackGui this->m_columns.addColumn(CColumn("longitude", CAirport::IndexLatitude, new CLatLonFormatter())); // default sort order - this->setSortColumnByPropertyIndex(CAirport::IndexDistance); + this->setSortColumnByPropertyIndex(CAirport::IndexDistanceToOwnAircraft); this->m_sortOrder = Qt::AscendingOrder; // force strings for translation in resource files diff --git a/src/blackgui/models/atcstationlistmodel.cpp b/src/blackgui/models/atcstationlistmodel.cpp index 6b54c2d82..5eb7fc00a 100644 --- a/src/blackgui/models/atcstationlistmodel.cpp +++ b/src/blackgui/models/atcstationlistmodel.cpp @@ -54,7 +54,7 @@ namespace BlackGui CColumn col = CColumn("type", CAtcStation::IndexIcon); col.setSortPropertyIndex({ CAtcStation::IndexCallsign, CCallsign::IndexSuffix }); this->m_columns.addColumn(col); - this->m_columns.addColumn(CColumn("distance", CAtcStation::IndexDistance, new CAirspaceDistanceFormatter())); + this->m_columns.addColumn(CColumn("distance", CAtcStation::IndexDistanceToOwnAircraft, new CAirspaceDistanceFormatter())); this->m_columns.addColumn(CColumn("frequency", CAtcStation::IndexFrequency, new CComFrequencyFormatter())); this->m_columns.addColumn(CColumn::standardString("controllername", { CAtcStation::IndexController, CUser::IndexRealName })); this->m_columns.addColumn(CColumn("from", "booked from", CAtcStation::IndexBookedFrom, new CDateTimeFormatter(CDateTimeFormatter::formatHm()))); @@ -62,7 +62,7 @@ namespace BlackGui this->m_columns.addColumn(CColumn::standardString("voiceroomurl", { CAtcStation::IndexVoiceRoom, CVoiceRoom::IndexUrl })); // default sort order - this->setSortColumnByPropertyIndex(CAtcStation::IndexDistance); + this->setSortColumnByPropertyIndex(CAtcStation::IndexDistanceToOwnAircraft); this->m_sortOrder = Qt::AscendingOrder; } break; @@ -115,7 +115,7 @@ namespace BlackGui new QStandardItem(station.getCallsign().toQString()), new QStandardItem(station.getFrequency().valueRoundedWithUnit(CFrequencyUnit::MHz(), 2, true)), new QStandardItem(station.getControllerRealName()), - new QStandardItem(station.getDistanceToPlane().valueRoundedWithUnit(CLengthUnit::NM(), 1, true)) + new QStandardItem(station.getDistanceToOwnAircraft().valueRoundedWithUnit(CLengthUnit::NM(), 1, true)) }; break; case StationsBooked: diff --git a/src/blackgui/models/simulatedaircraftlistmodel.cpp b/src/blackgui/models/simulatedaircraftlistmodel.cpp index 6e8227e74..4d319e59a 100644 --- a/src/blackgui/models/simulatedaircraftlistmodel.cpp +++ b/src/blackgui/models/simulatedaircraftlistmodel.cpp @@ -53,7 +53,7 @@ namespace BlackGui case InfoMode: this->m_columns.addColumn(CColumn::standardValueObject("cs.", "callsign", CSimulatedAircraft::IndexCallsign, CCallsign::IndexCallsignString)); this->m_columns.addColumn(CColumn::standardString("realname", "pilot's real name", { CSimulatedAircraft::IndexPilot, CUser::IndexRealName })); - this->m_columns.addColumn(CColumn("distance", CSimulatedAircraft::IndexDistance, new CAirspaceDistanceFormatter())); + this->m_columns.addColumn(CColumn("distance", CSimulatedAircraft::IndexDistanceToOwnAircraft, new CAirspaceDistanceFormatter())); this->m_columns.addColumn(CColumn("frequency", { CSimulatedAircraft::IndexCom1System, CComSystem::IndexActiveFrequency }, new CComFrequencyFormatter())); this->m_columns.addColumn(CColumn::standardString("icao", { CSimulatedAircraft::IndexIcao, CAircraftIcao::IndexAsString})); this->m_columns.addColumn(CColumn::standardString("transponder", { CSimulatedAircraft::IndexTransponder, CTransponder::IndexTransponderCodeAndModeFormatted })); @@ -63,7 +63,7 @@ namespace BlackGui this->m_columns.addColumn(CColumn("gs.", { CSimulatedAircraft::IndexSituation, CAircraftSituation::IndexGroundspeed }, new CAircraftSpeedFormatter())); // default sort order - this->setSortColumnByPropertyIndex(CSimulatedAircraft::IndexDistance); + this->setSortColumnByPropertyIndex(CSimulatedAircraft::IndexDistanceToOwnAircraft); this->m_sortOrder = Qt::AscendingOrder; break; @@ -72,7 +72,7 @@ namespace BlackGui new CBoolIconFormatter(CIcons::StandardIconTick16, CIcons::StandardIconCross16, "enabled", "disabled"), true)); this->m_columns.addColumn(CColumn::standardValueObject("cs.", "callsign", { CSimulatedAircraft::IndexCallsign, CCallsign::IndexCallsignString })); this->m_columns.addColumn(CColumn::standardString("realname", "pilot's real name", { CSimulatedAircraft::IndexPilot, CUser::IndexRealName })); - this->m_columns.addColumn(CColumn("distance", CSimulatedAircraft::IndexDistance, new CAirspaceDistanceFormatter())); + this->m_columns.addColumn(CColumn("distance", CSimulatedAircraft::IndexDistanceToOwnAircraft, new CAirspaceDistanceFormatter())); this->m_columns.addColumn(CColumn::standardString("icao", { CSimulatedAircraft::IndexIcao, CAircraftIcao::IndexAsString})); this->m_columns.addColumn(CColumn::standardString("model", { CSimulatedAircraft::IndexModel, CAircraftModel::IndexModelString})); this->m_columns.addColumn(CColumn::standardString("desc.", "description", { CSimulatedAircraft::IndexModel, CAircraftModel::IndexDescription})); diff --git a/src/blackmisc/avaircraft.cpp b/src/blackmisc/avaircraft.cpp index d3d37ff96..74659da01 100644 --- a/src/blackmisc/avaircraft.cpp +++ b/src/blackmisc/avaircraft.cpp @@ -26,12 +26,10 @@ namespace BlackMisc if (!this->m_pilot.hasValidCallsign() && !callsign.isEmpty()) { this->m_pilot.setCallsign(callsign); + this->m_situation.setCallsign(callsign); } } - /* - * Convert to string - */ QString CAircraft::convertToQString(bool i18n) const { QString s(this->m_callsign.toQString(i18n)); @@ -43,18 +41,6 @@ namespace BlackMisc return s; } - /* - * Distance to plane - */ - const PhysicalQuantities::CLength &CAircraft::setCalculcatedDistanceToPosition(const Geo::CCoordinateGeodetic &position) - { - this->m_distanceToPlane = Geo::greatCircleDistance(position, this->m_situation.getPosition()); - return this->m_distanceToPlane; - } - - /* - * Set cockpit data - */ void CAircraft::setCockpit(const CComSystem &com1, const CComSystem &com2, const CTransponder &transponder) { this->setCom1System(com1); @@ -62,9 +48,6 @@ namespace BlackMisc this->setTransponder(transponder); } - /* - * Set cockpit data - */ void CAircraft::setCockpit(const CComSystem &com1, const CComSystem &com2, int transponderCode, CTransponder::TransponderMode transponderMode) { this->setCom1System(com1); @@ -73,44 +56,29 @@ namespace BlackMisc this->m_transponder.setTransponderMode(transponderMode); } - /* - * Changed data - */ bool CAircraft::hasChangedCockpitData(const CComSystem &com1, const CComSystem &com2, const CTransponder &transponder) const { return this->getCom1System() != com1 || this->getCom2System() != com2 || this->getTransponder() != transponder; } - /* - * Distance to plane - */ - PhysicalQuantities::CLength CAircraft::calculcateDistanceToPosition(const Geo::CCoordinateGeodetic &position) const - { - return Geo::greatCircleDistance(position, this->m_situation.getPosition()); - } - - - /* - * Same COM system data - */ bool CAircraft::hasSameComData(const CComSystem &com1, const CComSystem &com2, const CTransponder &transponder) { return this->getCom1System() == com1 && this->getCom2System() == com2 && this->getTransponder() == transponder; } - /* - * Valid for login - */ bool CAircraft::isValidForLogin() const { - if (this->m_callsign.asString().isEmpty()) return false; - if (!this->m_pilot.isValid()) return false; + if (this->m_callsign.asString().isEmpty()) { return false; } + if (!this->m_pilot.isValid()) { return false; } return true; } - /* - * Meaningful values - */ + void CAircraft::setSituation(const CAircraftSituation &situation) + { + m_situation = situation; + m_situation.setCallsign(this->getCallsign()); + } + void CAircraft::initComSystems() { CComSystem com1("COM1", CPhysicalQuantitiesConstants::FrequencyUnicom(), CPhysicalQuantitiesConstants::FrequencyUnicom()); @@ -119,18 +87,12 @@ namespace BlackMisc this->setCom2System(com2); } - /* - * Meaningful values - */ void CAircraft::initTransponder() { CTransponder xpdr("TRANSPONDER", 7000, CTransponder::StateStandby); this->setTransponder(xpdr); } - /* - * Property by index - */ CVariant CAircraft::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return this->toCVariant(); } @@ -141,8 +103,8 @@ namespace BlackMisc return this->m_callsign.propertyByIndex(index.copyFrontRemoved()); case IndexPilot: return this->m_pilot.propertyByIndex(index.copyFrontRemoved()); - case IndexDistance: - return this->m_distanceToPlane.propertyByIndex(index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved()); case IndexCom1System: return this->m_com1system.propertyByIndex(index.copyFrontRemoved()); case IndexCom2System: @@ -160,9 +122,6 @@ namespace BlackMisc } } - /* - * Property by index (setter) - */ void CAircraft::setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index) { if (index.isMyself()) @@ -179,8 +138,8 @@ namespace BlackMisc case IndexPilot: this->m_pilot.setPropertyByIndex(variant, index.copyFrontRemoved()); break; - case IndexDistance: - this->m_distanceToPlane.setPropertyByIndex(variant, index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + this->m_distanceToOwnAircraft.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexCom1System: this->m_com1system.setPropertyByIndex(variant, index.copyFrontRemoved()); diff --git a/src/blackmisc/avaircraft.h b/src/blackmisc/avaircraft.h index f8cccdaf6..b7b227453 100644 --- a/src/blackmisc/avaircraft.h +++ b/src/blackmisc/avaircraft.h @@ -29,7 +29,7 @@ namespace BlackMisc namespace Aviation { //! Value object encapsulating information of an aircraft - class CAircraft : public CValueObjectStdTuple, public Geo::ICoordinateGeodetic + class CAircraft : public CValueObjectStdTuple, public BlackMisc::Geo::ICoordinateWithRelativePosition { public: //! Properties by index @@ -37,7 +37,7 @@ namespace BlackMisc { IndexCallsign = BlackMisc::CPropertyIndex::GlobalIndexCAircraft, IndexPilot, - IndexDistance, + IndexDistanceToOwnAircraft, IndexCom1System, IndexCom2System, IndexTransponder, @@ -67,7 +67,7 @@ namespace BlackMisc const CAircraftSituation &getSituation() const { return m_situation; } //! Set situation. - void setSituation(const CAircraftSituation &situation) { m_situation = situation; } + void setSituation(const CAircraftSituation &situation); //! Get user const BlackMisc::Network::CUser &getPilot() const { return m_pilot; } @@ -87,15 +87,6 @@ namespace BlackMisc //! Set ICAO info virtual void setIcaoInfo(const CAircraftIcao &icao) { m_icao = icao; } - //! 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.isNegativeWithEpsilonConsidered();} - //! Has valid realname? bool hasValidRealName() const { return this->m_pilot.hasValidRealName(); } @@ -111,15 +102,6 @@ namespace BlackMisc //! Valid callsign bool hasValidCallsign() const { return CCallsign::isValidCallsign(this->getCallsign().asString()); } - //! Distance to aircraft - PhysicalQuantities::CLength calculcateDistanceToPosition(const Geo::CCoordinateGeodetic &position) const; - - /*! - * Calculcate distance to plane, set it, and also return it - * \param position calculated from this postion to my own aircraft - */ - const BlackMisc::PhysicalQuantities::CLength &setCalculcatedDistanceToPosition(const BlackMisc::Geo::CCoordinateGeodetic &position); - //! Get position BlackMisc::Geo::CCoordinateGeodetic getPosition() const { return this->m_situation.getPosition(); } @@ -141,8 +123,17 @@ namespace BlackMisc //! \copydoc ICoordinateGeodetic::longitude virtual const BlackMisc::Geo::CLongitude &longitude() const override { return this->m_situation.longitude(); } - //! \copydoc CCoordinateGeodetic::height - const BlackMisc::PhysicalQuantities::CLength &getHeight() const { return this->m_situation.getHeight(); } + //! \copydoc ICoordinateGeodetic::geodeticHeight + //! \remarks this should be used for elevation as depicted here: http://en.wikipedia.org/wiki/Altitude#mediaviewer/File:Vertical_distances.svg + const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const override { return this->m_situation.geodeticHeight(); } + + //! Elevation + //! \sa geodeticHeight + const BlackMisc::PhysicalQuantities::CLength getElevation() const { return this->geodeticHeight(); } + + //! Elevation + //! \sa setGeodeticHeight + void setElevation(const BlackMisc::PhysicalQuantities::CLength &elevation) { return this->m_situation.setElevation(elevation); } //! Get heading const BlackMisc::Aviation::CHeading &getHeading() const { return this->m_situation.getHeading(); } @@ -253,12 +244,11 @@ namespace BlackMisc CTransponder m_transponder; CSelcal m_selcal; CAircraftIcao m_icao; - BlackMisc::PhysicalQuantities::CLength m_distanceToPlane {0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit()}; }; } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraft, (o.m_callsign, o.m_pilot, o.m_situation, o.m_com1system, o.m_com2system, o.m_transponder, o.m_icao, o.m_distanceToPlane)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraft, (o.m_callsign, o.m_pilot, o.m_situation, o.m_com1system, o.m_com2system, o.m_transponder, o.m_icao, o.m_distanceToOwnAircraft, o.m_bearingToOwnAircraft)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraft) #endif // guard diff --git a/src/blackmisc/avaircraftlist.cpp b/src/blackmisc/avaircraftlist.cpp index 06ce4886f..f42e35da4 100644 --- a/src/blackmisc/avaircraftlist.cpp +++ b/src/blackmisc/avaircraftlist.cpp @@ -32,23 +32,6 @@ namespace BlackMisc CSequence(other) { } - /* - * Contains callsign - */ - bool CAircraftList::containsCallsign(const CCallsign &callsign) const - { - if (callsign.isEmpty()) { return false; } - return this->contains(&CAircraft::getCallsign, callsign); - } - - /* - * Change for callsign - */ - int CAircraftList::applyIfCallsign(const CCallsign &callsign, const CPropertyIndexVariantMap &variantMap) - { - return this->applyIf(&CAircraft::getCallsign, callsign, variantMap, false); - } - /* * Register metadata */ @@ -63,30 +46,6 @@ namespace BlackMisc registerMetaValueType(); } - /* - * Find by callsign - */ - CAircraftList CAircraftList::findByCallsign(const CCallsign &callsign) const - { - return this->findBy(&CAircraft::getCallsign, callsign); - } - - /* - * Find by callsigns - */ - CAircraftList CAircraftList::findByCallsigns(const CCallsignList &callsigns) const - { - return this->findBy(Predicates::MemberIsAnyOf(&CAircraft::getCallsign, callsigns)); - } - - /* - * Find by callsign - */ - CAircraft CAircraftList::findFirstByCallsign(const CCallsign &callsign, const CAircraft &ifNotFound) const - { - return this->findByCallsign(callsign).frontOrDefault(ifNotFound); - } - /* * All pilots */ @@ -95,17 +54,6 @@ namespace BlackMisc return this->findBy(Predicates::MemberValid(&CAircraft::getPilot)).transform(Predicates::MemberTransform(&CAircraft::getPilot)); } - /* - * Aircrafts within range - */ - CAircraftList CAircraftList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const - { - return this->findBy([&](const CAircraft & aircraft) - { - return BlackMisc::Geo::greatCircleDistance(aircraft, coordinate) <= range; - }); - } - /* * Merge with aircraft */ diff --git a/src/blackmisc/avaircraftlist.h b/src/blackmisc/avaircraftlist.h index 2b3678f98..6733d31ae 100644 --- a/src/blackmisc/avaircraftlist.h +++ b/src/blackmisc/avaircraftlist.h @@ -14,9 +14,10 @@ #include "avaircraft.h" #include "avcallsignlist.h" +#include "avcallsignobjectlist.h" +#include "geoobjectlist.h" #include "nwuserlist.h" #include "collection.h" -#include "sequence.h" #include "propertyindexvariantmap.h" #include #include @@ -27,7 +28,10 @@ namespace BlackMisc namespace Aviation { //! Value object encapsulating a list of aircraft. - class CAircraftList : public CSequence + class CAircraftList : + public CSequence, + public ICallsignObjectList, + public BlackMisc::Geo::IGeoObjectList { public: //! Default constructor. @@ -36,32 +40,9 @@ namespace BlackMisc //! Construct from a base class object. CAircraftList(const CSequence &other); - //! Contains callsign? - bool containsCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; - - //! Apply for given callsign - int applyIfCallsign(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &variantMap); - - //! Find 0..n stations by callsign - CAircraftList findByCallsign(const CCallsign &callsign) const; - - //! Find 0..n aircraft matching any of a set of callsigns - CAircraftList findByCallsigns(const CCallsignList &callsigns) const; - - //! Find the first aircraft by callsign, if none return given one - CAircraft findFirstByCallsign(const CCallsign &callsign, const CAircraft &ifNotFound = CAircraft()) const; - //! All pilots (with valid data) BlackMisc::Network::CUserList getPilots() const; - /*! - * Find 0..n stations within range of given coordinate - * \param coordinate other position - * \param range within range of other position - * \return - */ - CAircraftList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; - //! \brief Update aircraft with data from VATSIM data file //! \remarks The list used needs to contain the VATSIM data file objects bool updateWithVatsimDataFileData(CAircraft &aircraftToBeUpdated) const; @@ -74,6 +55,14 @@ namespace BlackMisc //! Register metadata static void registerMetadata(); + + protected: + //! Myself + virtual const CAircraftList &getContainer() const { return *this; } + + //! Myself + virtual CAircraftList &getContainer() { return *this; } + }; } //namespace diff --git a/src/blackmisc/avaircraftsituation.cpp b/src/blackmisc/avaircraftsituation.cpp index a6b1df7b7..23a075f13 100644 --- a/src/blackmisc/avaircraftsituation.cpp +++ b/src/blackmisc/avaircraftsituation.cpp @@ -31,7 +31,7 @@ namespace BlackMisc s.append(" pitch: ").append(this->m_pitch.toQString(i18n)); s.append(" gs: ").append(this->m_groundspeed.toQString(i18n)); s.append(" heading: ").append(this->m_heading.toQString(i18n)); - s.append(" timestamp: ").append(this->m_timestamp.toString("dd hh:mm:ss")); + s.append(" timestamp: ").append(this->getFormattedUtcTimestamp()); return s; } @@ -41,6 +41,11 @@ namespace BlackMisc CVariant CAircraftSituation::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return this->toCVariant(); } + if (ITimestampBased::canHandleIndex(index)) + { + return ITimestampBased::propertyByIndex(index); + } + ColumnIndex i = index.frontCasted(); switch (i) { @@ -60,10 +65,8 @@ namespace BlackMisc return this->m_bank.propertyByIndex(index.copyFrontRemoved()); case IndexGroundspeed: return this->m_groundspeed.propertyByIndex(index.copyFrontRemoved()); - case IndexTimeStamp: - return CVariant::fromValue(this->m_timestamp); - case IndexTimeStampFormatted: - return CVariant::fromValue(this->m_groundspeed.toQString("dd hh:mm:ss")); + case IndexCallsign: + return this->m_correspondingCallsign.propertyByIndex(index.copyFrontRemoved()); default: break; } @@ -102,6 +105,9 @@ namespace BlackMisc case IndexGroundspeed: this->m_groundspeed.setPropertyByIndex(variant, index.copyFrontRemoved()); break; + case IndexCallsign: + this->m_correspondingCallsign.setPropertyByIndex(variant, index.copyFrontRemoved()); + break; default: Q_ASSERT_X(false, "CAircraftSituation", "index unknown (setter)"); break; diff --git a/src/blackmisc/avaircraftsituation.h b/src/blackmisc/avaircraftsituation.h index 4b7580822..41d54c684 100644 --- a/src/blackmisc/avaircraftsituation.h +++ b/src/blackmisc/avaircraftsituation.h @@ -13,8 +13,10 @@ #define BLACKMISC_AIRCRAFTSITUATION_H #include "coordinategeodetic.h" +#include "timestampbased.h" #include "avaltitude.h" #include "avheading.h" +#include "avcallsign.h" #include "pqspeed.h" #include "valueobject.h" #include @@ -26,7 +28,9 @@ namespace BlackMisc /*! * Value object encapsulating information of an aircraft's situation */ - class CAircraftSituation : public CValueObjectStdTuple, public Geo::ICoordinateGeodetic + class CAircraftSituation : + public CValueObjectStdTuple, + public Geo::ICoordinateGeodetic, public BlackMisc::ITimestampBased { public: //! Properties by index @@ -40,21 +44,32 @@ namespace BlackMisc IndexBank, IndexPitch, IndexGroundspeed, - IndexTimeStamp, - IndexTimeStampFormatted + IndexCallsign }; //! Default constructor. - CAircraftSituation() : m_timestamp(QDateTime::currentDateTimeUtc()) {} + CAircraftSituation() {} - //! Comprehensive Constructor + //! Comprehensive constructor CAircraftSituation(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude, - const BlackMisc::Aviation::CHeading &heading = BlackMisc::Aviation::CHeading(), - const BlackMisc::PhysicalQuantities::CAngle &pitch = BlackMisc::PhysicalQuantities::CAngle(), - const BlackMisc::PhysicalQuantities::CAngle &bank = BlackMisc::PhysicalQuantities::CAngle(), - const BlackMisc::PhysicalQuantities::CSpeed &gs = BlackMisc::PhysicalQuantities::CSpeed()) + const BlackMisc::Aviation::CHeading &heading = {}, + const BlackMisc::PhysicalQuantities::CAngle &pitch = {}, + const BlackMisc::PhysicalQuantities::CAngle &bank = {}, + const BlackMisc::PhysicalQuantities::CSpeed &gs = {}) : m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), - m_bank(bank), m_groundspeed(gs), m_timestamp(QDateTime::currentDateTimeUtc()) {} + m_bank(bank), m_groundspeed(gs) {} + + //! Comprehensive constructor + CAircraftSituation(const BlackMisc::Aviation::CCallsign &correspondingCallsign, + const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude, + const BlackMisc::Aviation::CHeading &heading = {}, + const BlackMisc::PhysicalQuantities::CAngle &pitch = {}, + const BlackMisc::PhysicalQuantities::CAngle &bank = {}, + const BlackMisc::PhysicalQuantities::CSpeed &gs = {}) + : m_correspondingCallsign(correspondingCallsign), + m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), + m_bank(bank), m_groundspeed(gs) {} + //! \copydoc CValueObject::propertyByIndex virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override; @@ -74,11 +89,17 @@ namespace BlackMisc //! \copydoc ICoordinateGeodetic::longitude() virtual const BlackMisc::Geo::CLongitude &longitude() const override { return this->m_position.longitude(); } - //! \copydoc CCoordinateGeodetic::height - const BlackMisc::PhysicalQuantities::CLength &getHeight() const { return this->m_position.geodeticHeight(); } + //! \copydoc ICoordinateGeodetic::geodeticHeight + //! \remarks this should be used for elevation as depicted here: http://en.wikipedia.org/wiki/Altitude#mediaviewer/File:Vertical_distances.svg + const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const override { return this->m_position.geodeticHeight(); } - //! Set height - void setHeight(const BlackMisc::PhysicalQuantities::CLength &height) { this->m_position.setGeodeticHeight(height); } + //! Elevation + //! \sa geodeticHeight + const BlackMisc::PhysicalQuantities::CLength getElevation() const { return this->geodeticHeight(); } + + //! Elevation + //! \sa setGeodeticHeight + void setElevation(const BlackMisc::PhysicalQuantities::CLength &elevation) { return this->m_position.setGeodeticHeight(elevation); } //! Get heading const BlackMisc::Aviation::CHeading &getHeading() const { return this->m_heading; } @@ -110,8 +131,11 @@ namespace BlackMisc //! Set groundspeed void setGroundspeed(const BlackMisc::PhysicalQuantities::CSpeed &groundspeed) { this->m_groundspeed = groundspeed; } - //! Timestamp - const QDateTime &getTimestamp() const { return this->m_timestamp;} + //! Corresponding callsign + const BlackMisc::Aviation::CCallsign &getCallsign() const { return this->m_correspondingCallsign; } + + //! Corresponding callsign + void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) { this->m_correspondingCallsign = callsign; } protected: //! \copydoc CValueObject::convertToQString @@ -119,18 +143,18 @@ namespace BlackMisc private: BLACK_ENABLE_TUPLE_CONVERSION(CAircraftSituation) + CCallsign m_correspondingCallsign; BlackMisc::Geo::CCoordinateGeodetic m_position; BlackMisc::Aviation::CAltitude m_altitude; - BlackMisc::Aviation::CHeading m_heading; + BlackMisc::Aviation::CHeading m_heading; BlackMisc::PhysicalQuantities::CAngle m_pitch; BlackMisc::PhysicalQuantities::CAngle m_bank; BlackMisc::PhysicalQuantities::CSpeed m_groundspeed; - QDateTime m_timestamp; }; } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraftSituation, (o.m_position, o.m_altitude, o.m_heading, o.m_pitch, o.m_bank, o.m_groundspeed)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraftSituation, (o.m_correspondingCallsign, o.m_position, o.m_altitude, o.m_heading, o.m_pitch, o.m_bank, o.m_groundspeed)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftSituation) #endif // guard diff --git a/src/blackmisc/avaircraftsituationlist.cpp b/src/blackmisc/avaircraftsituationlist.cpp index 324f5d8b3..d708495c8 100644 --- a/src/blackmisc/avaircraftsituationlist.cpp +++ b/src/blackmisc/avaircraftsituationlist.cpp @@ -1,9 +1,11 @@ -#include "avaircraftsituationlist.h" - -/* 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/. */ +/* Copyright (C) 2013 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ #include "avaircraftsituationlist.h" #include "predicates.h" @@ -15,47 +17,11 @@ namespace BlackMisc namespace Aviation { CAircraftSituationList::CAircraftSituationList() - { - } + { } - /* - * Construct from base class object - */ CAircraftSituationList::CAircraftSituationList(const CSequence &other) : CSequence(other) { } - CAircraftSituationList CAircraftSituationList::findBefore(const QDateTime &dateTime) const - { - return findBy([&](const CAircraftSituation & situation) - { - return situation.getTimestamp() < dateTime; - }); - } - - CAircraftSituationList CAircraftSituationList::findAfter(const QDateTime &dateTime) const - { - return findBy([&](const CAircraftSituation & situation) - { - return situation.getTimestamp() > dateTime; - }); - } - - void CAircraftSituationList::removeBefore(const QDateTime &dateTime) - { - removeIf([&](const CAircraftSituation & situation) - { - return situation.getTimestamp() < dateTime; - }); - } - - void CAircraftSituationList::removeOlderThan(double seconds) - { - removeIf([&](const CAircraftSituation & situation) - { - return situation.getTimestamp() < QDateTime::currentDateTimeUtc().addSecs(-seconds); - }); - } - } // namespace } // namespace diff --git a/src/blackmisc/avaircraftsituationlist.h b/src/blackmisc/avaircraftsituationlist.h index cd504965d..e9215f921 100644 --- a/src/blackmisc/avaircraftsituationlist.h +++ b/src/blackmisc/avaircraftsituationlist.h @@ -1,7 +1,11 @@ -/* 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/. */ +/* Copyright (C) 2013 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ //! \file @@ -9,6 +13,8 @@ #define BLACKMISC_AVAIRCRAFTSITUATIONLIST_H #include "avaircraftsituation.h" +#include "timestampobjectlist.h" +#include "avcallsignobjectlist.h" #include "sequence.h" namespace BlackMisc @@ -16,7 +22,10 @@ namespace BlackMisc namespace Aviation { //! Value object encapsulating a list of aircraft situations - class CAircraftSituationList : public CSequence + class CAircraftSituationList : + public CSequence, + public ITimestampObjectList, + public ICallsignObjectList { public: //! Default constructor. @@ -25,36 +34,22 @@ namespace BlackMisc //! Construct from a base class object. CAircraftSituationList(const CSequence &other); - /*! - * Get a list of situations before dateTime - */ - CAircraftSituationList findBefore (const QDateTime& dateTime) const; - - /*! - * Get a list of situations after dateTime - */ - CAircraftSituationList findAfter (const QDateTime& dateTime) const; - - /*! - * Remove situations with timestamp before dateTime - */ - void removeBefore(const QDateTime& dateTime); - - /*! - * Remove situations older than seconds - * \param seconds - */ - void removeOlderThan(double seconds); - //! \copydoc CValueObject::toQVariant virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); } //! \copydoc CValueObject::convertFromQVariant virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); } + protected: + //! Myself + virtual const CAircraftSituationList &getContainer() const { return *this; } + + //! Myself + virtual CAircraftSituationList &getContainer() { return *this; } + }; - } -} + } // namespace +} // namespace Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftSituationList) Q_DECLARE_METATYPE(BlackMisc::CSequence) diff --git a/src/blackmisc/avairport.cpp b/src/blackmisc/avairport.cpp index 296d82d5b..36f01848e 100644 --- a/src/blackmisc/avairport.cpp +++ b/src/blackmisc/avairport.cpp @@ -22,29 +22,28 @@ namespace BlackMisc /* * Constructor */ - CAirport::CAirport() : - m_distanceToPlane(0, CLengthUnit::nullUnit()) + CAirport::CAirport() { } /* * Constructor */ CAirport::CAirport(const QString &icao) : - m_icao(icao), m_distanceToPlane(0, CLengthUnit::nullUnit()) + m_icao(icao) { } /* * Constructor */ CAirport::CAirport(const CAirportIcao &icao, const BlackMisc::Geo::CCoordinateGeodetic &position) : - m_icao(icao), m_position(position), m_distanceToPlane(0, CLengthUnit::nullUnit()) + m_icao(icao), m_position(position) { } /* * Constructor */ CAirport::CAirport(const CAirportIcao &icao, const BlackMisc::Geo::CCoordinateGeodetic &position, const QString &descriptiveName) : - m_icao(icao), m_descriptiveName(descriptiveName), m_position(position), m_distanceToPlane(0, CLengthUnit::nullUnit()) + m_icao(icao), m_descriptiveName(descriptiveName), m_position(position) { } /* @@ -66,17 +65,6 @@ namespace BlackMisc (void)QT_TRANSLATE_NOOP("Aviation", "ATC station"); } - /* - * Distance to planne - */ - CLength CAirport::calculcateDistanceAndBearingToPlane(const CCoordinateGeodetic &position, bool updateValues) - { - if (!updateValues) return Geo::greatCircleDistance(this->m_position, position); - this->m_distanceToPlane = Geo::greatCircleDistance(this->m_position, position); - this->m_bearingToPlane = Geo::initialBearing(this->m_position, position); - return this->m_distanceToPlane; - } - /* * Property by index */ @@ -95,9 +83,9 @@ namespace BlackMisc case IndexElevation: return this->getElevation().propertyByIndex(index.copyFrontRemoved()); case IndexBearing: - return this->m_bearingToPlane.propertyByIndex(index.copyFrontRemoved()); - case IndexDistance: - return this->m_distanceToPlane.propertyByIndex(index.copyFrontRemoved()); + return this->m_bearingToOwnAircraft.propertyByIndex(index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved()); default: return (ICoordinateGeodetic::canHandleIndex(index)) ? ICoordinateGeodetic::propertyByIndex(index) : @@ -128,10 +116,10 @@ namespace BlackMisc this->m_position.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexBearing: - this->m_bearingToPlane.setPropertyByIndex(variant, index.copyFrontRemoved()); + this->m_bearingToOwnAircraft.setPropertyByIndex(variant, index.copyFrontRemoved()); break; - case IndexDistance: - this->m_distanceToPlane.setPropertyByIndex(variant, index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + this->m_distanceToOwnAircraft.setPropertyByIndex(variant, index.copyFrontRemoved()); break; default: CValueObject::setPropertyByIndex(variant, index); diff --git a/src/blackmisc/avairport.h b/src/blackmisc/avairport.h index 0a5bb66a3..4caa66122 100644 --- a/src/blackmisc/avairport.h +++ b/src/blackmisc/avairport.h @@ -23,7 +23,7 @@ namespace BlackMisc /*! * Value object encapsulating information about an airpot. */ - class CAirport : public CValueObjectStdTuple, public Geo::ICoordinateGeodetic + class CAirport : public CValueObjectStdTuple, public Geo::ICoordinateWithRelativePosition { public: //! Properties by index @@ -33,7 +33,7 @@ namespace BlackMisc IndexDescriptiveName, IndexPosition, IndexElevation, - IndexDistance, + IndexDistanceToOwnAircraft, IndexBearing }; @@ -71,32 +71,20 @@ namespace BlackMisc void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_position = position; } //! Elevation - const BlackMisc::PhysicalQuantities::CLength getElevation() const { return this->getPosition().geodeticHeight(); } + //! \sa geodeticHeight + const BlackMisc::PhysicalQuantities::CLength getElevation() const { return this->geodeticHeight(); } - //! Get the distance to own plane - const BlackMisc::PhysicalQuantities::CLength &getDistanceToPlane() const { return m_distanceToPlane; } + //! Elevation + //! \sa setGeodeticHeight + void setElevation(const BlackMisc::PhysicalQuantities::CLength &elevation) { return this->m_position.setGeodeticHeight(elevation); } - //! Set distance to own plane - void setDistanceToPlane(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToPlane = distance; } - - //! Get the bearing to own plane - const BlackMisc::PhysicalQuantities::CAngle &getBearingToPlane() const { return m_bearingToPlane; } - - //! Set bearing to own plane - void setBearingToPlane(const BlackMisc::PhysicalQuantities::CAngle &angle) { this->m_bearingToPlane = angle; } - - //! Valid distance? - bool hasValidDistance() const { return !this->m_distanceToPlane.isNull();} - - //! Valid bearing? - bool hasValidBearing() const { return !this->m_bearingToPlane.isNull();} + //! \copydoc ICoordinateGeodetic::geodeticHeight + //! \remarks this should be used for elevation as depicted here: http://en.wikipedia.org/wiki/Altitude#mediaviewer/File:Vertical_distances.svg + const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const override { return this->m_position.geodeticHeight(); } //! Valid ICAO code bool hasValidIcaoCode() const { return !this->getIcao().isEmpty(); } - //! Calculcate distance and bearing to plane, set it, and return distance - BlackMisc::PhysicalQuantities::CLength calculcateDistanceAndBearingToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position, bool updateValues = true); - //! \copydoc ICoordinateGeodetic::latitude virtual const BlackMisc::Geo::CLatitude &latitude() const override { @@ -121,16 +109,14 @@ namespace BlackMisc private: BLACK_ENABLE_TUPLE_CONVERSION(CAirport) - CAirportIcao m_icao; - QString m_descriptiveName; + CAirportIcao m_icao; + QString m_descriptiveName; BlackMisc::Geo::CCoordinateGeodetic m_position; - BlackMisc::PhysicalQuantities::CAngle m_bearingToPlane; - BlackMisc::PhysicalQuantities::CLength m_distanceToPlane; // make mutable ? }; } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirport, (o.m_icao, o.m_position)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirport, (o.m_icao, o.m_descriptiveName, o.m_position, o.m_distanceToOwnAircraft, o.m_bearingToOwnAircraft)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirport) #endif // guard diff --git a/src/blackmisc/avairportlist.cpp b/src/blackmisc/avairportlist.cpp index 9734eb1fe..a6e674610 100644 --- a/src/blackmisc/avairportlist.cpp +++ b/src/blackmisc/avairportlist.cpp @@ -60,50 +60,5 @@ namespace BlackMisc return this->findByIcao(icao).frontOrDefault(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, bearing to own plane - */ - void CAirportList::calculcateDistanceAndBearingToPlane(const Geo::CCoordinateGeodetic &position) - { - std::for_each(this->begin(), this->end(), [ & ](CAirport & airport) - { - airport.calculcateDistanceAndBearingToPlane(position); - }); - } - - /* - * Remove outside range - */ - void CAirportList::removeIfOutsideRange(const Geo::CCoordinateGeodetic &position, const CLength &maxDistance, bool updateValues) - { - this->removeIf([ & ](CAirport &airport) - { - return airport.calculcateDistanceAndBearingToPlane(position, updateValues) > maxDistance; - }); - } - - /* - * Sort by range - */ - void CAirportList::sortByRange(const BlackMisc::Geo::CCoordinateGeodetic &position, bool updateValues) - { - if (updateValues) - { - this->calculcateDistanceAndBearingToPlane(position); - } - this->sort([ & ](const CAirport &a, const CAirport &b) { return a.getDistanceToPlane() < b.getDistanceToPlane(); }); - } - } // namespace } // namespace diff --git a/src/blackmisc/avairportlist.h b/src/blackmisc/avairportlist.h index da53301c1..92f721cf7 100644 --- a/src/blackmisc/avairportlist.h +++ b/src/blackmisc/avairportlist.h @@ -1,16 +1,22 @@ -/* 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/. */ +/* Copyright (C) 2013 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ //! \file #ifndef BLACKMISC_AIRPORTLIST_H #define BLACKMISC_AIRPORTLIST_H -#include "avairport.h" -#include "collection.h" -#include "sequence.h" +#include "blackmisc/avairport.h" +#include "blackmisc/geoobjectlist.h" +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include "blackmisc/geoobjectlist.h" #include #include #include @@ -22,7 +28,9 @@ namespace BlackMisc /*! * Value object for a list of airports. */ - class CAirportList : public CSequence + class CAirportList : + public CSequence, + public BlackMisc::Geo::IGeoObjectWithRelativePositionList { public: //! Default constructor. @@ -40,18 +48,6 @@ namespace BlackMisc //! 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 calculcateDistanceAndBearingToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); - - //! Remove if outside given radius - void removeIfOutsideRange(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &maxDistance, bool updateDistance); - - //! Sort by range from a given coordinate - void sortByRange(const BlackMisc::Geo::CCoordinateGeodetic &position, bool updateDistance); - //! \copydoc CValueObject::toQVariant virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); } @@ -60,6 +56,14 @@ namespace BlackMisc //! Register metadata static void registerMetadata(); + + protected: + //! Myself + virtual const CAirportList &getContainer() const override { return *this; } + + //! Myself + virtual CAirportList &getContainer() override { return *this; } + }; } //namespace } // namespace diff --git a/src/blackmisc/avatcstation.cpp b/src/blackmisc/avatcstation.cpp index aa190db2d..8469ec486 100644 --- a/src/blackmisc/avatcstation.cpp +++ b/src/blackmisc/avatcstation.cpp @@ -28,8 +28,7 @@ namespace BlackMisc /* * Constructor */ - CAtcStation::CAtcStation() : - m_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR) + CAtcStation::CAtcStation() { // void } @@ -37,8 +36,7 @@ namespace BlackMisc /* * Constructor */ - CAtcStation::CAtcStation(const QString &callsign) : - m_callsign(callsign), m_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR) + CAtcStation::CAtcStation(const QString &callsign) : m_callsign(callsign) { // void } @@ -49,8 +47,7 @@ namespace BlackMisc CAtcStation::CAtcStation(const CCallsign &callsign, const CUser &controller, const CFrequency &frequency, const CCoordinateGeodetic &pos, const CLength &range, bool isOnline, const QDateTime &bookedFromUtc, const QDateTime &bookedUntilUtc, const CInformationMessage &atis, const CInformationMessage &metar) : m_callsign(callsign), m_controller(controller), m_frequency(frequency), m_position(pos), - m_range(range), m_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(isOnline), - m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), m_atis(atis), m_metar(metar) + m_range(range), m_isOnline(isOnline), m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), m_atis(atis), m_metar(metar) { // sync callsigns if (!this->m_controller.hasValidCallsign() && !callsign.isEmpty()) @@ -138,12 +135,12 @@ namespace BlackMisc s.append(this->m_range.toQString(i18n)); // distance to plane - if (this->m_distanceToPlane.isPositiveWithEpsilonConsidered()) + if (this->m_distanceToOwnAircraft.isPositiveWithEpsilonConsidered()) { s.append(' '); i18n ? s.append(QCoreApplication::translate("Aviation", "distance")) : s.append("distance"); s.append(' '); - s.append(this->m_distanceToPlane.toQString(i18n)); + s.append(this->m_distanceToOwnAircraft.toQString(i18n)); } // from / to @@ -207,16 +204,6 @@ namespace BlackMisc otherStation.setController(otherController); } - /* - * Distance to planne - */ - CLength CAtcStation::calculcateDistanceToPlane(const CCoordinateGeodetic &position, bool update) - { - if (!update) return Geo::greatCircleDistance(this->m_position, position); - this->m_distanceToPlane = Geo::greatCircleDistance(this->m_position, position); - return this->m_distanceToPlane; - } - /* * Booked now */ @@ -256,6 +243,30 @@ namespace BlackMisc } } + /* + * latitude + */ + const CLatitude &CAtcStation::latitude() const + { + return this->getPosition().latitude(); + } + + /* + * lomgitude + */ + const CLongitude &CAtcStation::longitude() const + { + return this->getPosition().longitude(); + } + + /* + * geodetic height + */ + const CLength &CAtcStation::geodeticHeight() const + { + return this->m_position.geodeticHeight(); + } + /* * Property by index */ @@ -279,8 +290,8 @@ namespace BlackMisc return CVariant::from(this->m_isOnline); case IndexLatitude: return this->latitude().propertyByIndex(index.copyFrontRemoved()); - case IndexDistance: - return this->m_distanceToPlane.propertyByIndex(index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved()); case IndexLongitude: return this->longitude().propertyByIndex(index.copyFrontRemoved()); case IndexPosition: @@ -332,8 +343,8 @@ namespace BlackMisc case IndexRange: this->m_range.setPropertyByIndex(variant, index.copyFrontRemoved()); break; - case IndexDistance: - this->m_distanceToPlane.setPropertyByIndex(variant, index.copyFrontRemoved()); + case IndexDistanceToOwnAircraft: + this->m_distanceToOwnAircraft.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexAtis: this->m_atis.setPropertyByIndex(variant, index.copyFrontRemoved()); diff --git a/src/blackmisc/avatcstation.h b/src/blackmisc/avatcstation.h index 180e018bb..86ff78f58 100644 --- a/src/blackmisc/avatcstation.h +++ b/src/blackmisc/avatcstation.h @@ -32,7 +32,7 @@ namespace BlackMisc /*! * Value object encapsulating information about an ATC station. */ - class CAtcStation : public CValueObjectStdTuple, public Geo::ICoordinateGeodetic + class CAtcStation : public CValueObjectStdTuple, public Geo::ICoordinateWithRelativePosition { public: //! Properties by index @@ -43,7 +43,7 @@ namespace BlackMisc IndexFrequency, IndexPosition, IndexRange, - IndexDistance, + IndexDistanceToOwnAircraft, IndexIsOnline, IndexBookedFrom, IndexBookedUntil, @@ -148,18 +148,6 @@ namespace BlackMisc //! Set range void setRange(const BlackMisc::PhysicalQuantities::CLength &range) { this->m_range = range; } - //! 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();} - - //! Calculcate distance to plane, set it, and also return it - BlackMisc::PhysicalQuantities::CLength calculcateDistanceToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position, bool update = true); - //! Is station online (or just booked)? bool isOnline() const { return m_isOnline; } @@ -243,16 +231,14 @@ namespace BlackMisc void setBookedUntilUtc(const QDateTime &until) { this->m_bookedUntilUtc = until; } //! \copydoc ICoordinateGeodetic::latitude - virtual const BlackMisc::Geo::CLatitude &latitude() const override - { - return this->getPosition().latitude(); - } + virtual const BlackMisc::Geo::CLatitude &latitude() const override; //! \copydoc ICoordinateGeodetic::longitude - virtual const BlackMisc::Geo::CLongitude &longitude() const override - { - return this->getPosition().longitude(); - } + virtual const BlackMisc::Geo::CLongitude &longitude() const override; + + //! \copydoc ICoordinateGeodetic::geodeticHeight + //! \remarks this should be used for elevation as depicted here: http://en.wikipedia.org/wiki/Altitude#mediaviewer/File:Vertical_distances.svg + const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const override; //! \copydoc CValueObject::propertyByIndex virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override; @@ -271,18 +257,17 @@ namespace BlackMisc BlackMisc::PhysicalQuantities::CFrequency m_frequency; BlackMisc::Geo::CCoordinateGeodetic m_position; BlackMisc::PhysicalQuantities::CLength m_range; - BlackMisc::PhysicalQuantities::CLength m_distanceToPlane; // make mutable ? - bool m_isOnline; + bool m_isOnline = false; QDateTime m_bookedFromUtc; QDateTime m_bookedUntilUtc; - CInformationMessage m_atis; - CInformationMessage m_metar; + CInformationMessage m_atis = { CInformationMessage::ATIS }; + CInformationMessage m_metar = { CInformationMessage::METAR }; BlackMisc::Audio::CVoiceRoom m_voiceRoom; }; } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAtcStation, (o.m_callsign, o.m_controller, o.m_frequency, o.m_position, o.m_range, o.m_isOnline, o.m_distanceToPlane, o.m_atis, o.m_bookedFromUtc, o.m_bookedUntilUtc, o.m_metar, o.m_voiceRoom)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAtcStation, (o.m_callsign, o.m_controller, o.m_frequency, o.m_position, o.m_range, o.m_isOnline, o.m_atis, o.m_bookedFromUtc, o.m_bookedUntilUtc, o.m_metar, o.m_voiceRoom, o.m_distanceToOwnAircraft, o.m_bearingToOwnAircraft)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CAtcStation) #endif // guard diff --git a/src/blackmisc/avatcstationlist.cpp b/src/blackmisc/avatcstationlist.cpp index 9d6b09032..dd3e295d0 100644 --- a/src/blackmisc/avatcstationlist.cpp +++ b/src/blackmisc/avatcstationlist.cpp @@ -1,7 +1,11 @@ -/* 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/. */ +/* Copyright (C) 2013 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ #include "avatcstationlist.h" #include "predicates.h" @@ -39,41 +43,6 @@ namespace BlackMisc registerMetaValueType(); } - /* - * Find by callsign - */ - CAtcStationList CAtcStationList::findByCallsign(const CCallsign &callsign) const - { - return this->findBy(&CAtcStation::getCallsign, callsign); - } - - /* - * Find by callsigns - */ - CAtcStationList CAtcStationList::findByCallsigns(const CCallsignList &callsigns) const - { - return this->findBy(Predicates::MemberIsAnyOf(&CAtcStation::getCallsign, callsigns)); - } - - /* - * Find first by callsign - */ - CAtcStation CAtcStationList::findFirstByCallsign(const CCallsign &callsign, const CAtcStation &ifNotFound) const - { - return this->findByCallsign(callsign).frontOrDefault(ifNotFound); - } - - /* - * Stations within range - */ - CAtcStationList CAtcStationList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const - { - return this->findBy([&](const CAtcStation & atcStation) - { - return greatCircleDistance(atcStation, coordinate) <= range; - }); - } - /* * Find if on frequency of COM unit */ @@ -85,28 +54,6 @@ namespace BlackMisc }); } - /* - * Find by suffix - */ - CAtcStationList CAtcStationList::findBySuffix(const QString &suffix) const - { - CAtcStationList r; - if (suffix.isEmpty()) { return r; } - r = this->findBy(&CAtcStation::getCallsignSuffix, suffix); - return r; - } - - /* - * Distances to own plane - */ - void CAtcStationList::calculateDistancesToPlane(const Geo::CCoordinateGeodetic &position) - { - std::for_each(this->begin(), this->end(), [ & ](CAtcStation & station) - { - station.calculcateDistanceToPlane(position); - }); - } - /* * All controllers */ @@ -115,28 +62,6 @@ namespace BlackMisc return this->findBy(Predicates::MemberValid(&CAtcStation::getController)).transform(Predicates::MemberTransform(&CAtcStation::getController)); } - /* - * Suffixes with count - */ - QMap CAtcStationList::getSuffixes() const - { - QMap r; - for (const CAtcStation &station : (*this)) - { - const QString s = station.getCallsignSuffix(); - if (s.isEmpty()) { continue; } - if (r.contains(s)) - { - r[s] = r[s] + 1; - } - else - { - r.insert(s, 1); - } - } - return r; - } - /* * Merge with booking, both (online/booking will be updated) */ @@ -205,11 +130,13 @@ namespace BlackMisc onlineAtcStation.syncronizeControllerData(bookedAtcStation); if (onlineAtcStation.hasValidDistance()) { - bookedAtcStation.setDistanceToPlane(onlineAtcStation.getDistanceToPlane()); + bookedAtcStation.setDistanceToOwnAircraft(onlineAtcStation.getDistanceToOwnAircraft()); + bookedAtcStation.setBearingToOwnAircraft(onlineAtcStation.getBearingToOwnAIrcraft()); } else if (bookedAtcStation.hasValidDistance()) { - onlineAtcStation.setDistanceToPlane(bookedAtcStation.getDistanceToPlane()); + onlineAtcStation.setDistanceToOwnAircraft(bookedAtcStation.getDistanceToOwnAircraft()); + onlineAtcStation.setBearingToOwnAircraft(bookedAtcStation.getBearingToOwnAIrcraft()); } // update @@ -248,5 +175,6 @@ namespace BlackMisc } return true; } + } // namespace } // namespace diff --git a/src/blackmisc/avatcstationlist.h b/src/blackmisc/avatcstationlist.h index 9e7ae0ee1..974fde621 100644 --- a/src/blackmisc/avatcstationlist.h +++ b/src/blackmisc/avatcstationlist.h @@ -1,7 +1,11 @@ -/* 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/. */ +/* Copyright (C) 2013 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ //! \file @@ -10,7 +14,7 @@ #include "nwuserlist.h" #include "avatcstation.h" -#include "avcallsignlist.h" +#include "avcallsignobjectlist.h" #include "collection.h" #include "sequence.h" #include @@ -24,7 +28,9 @@ namespace BlackMisc /*! * Value object for a list of ATC stations. */ - class CAtcStationList : public CSequence + class CAtcStationList : + public CSequence, + public ICallsignObjectList { public: //! Default constructor. @@ -33,33 +39,12 @@ namespace BlackMisc //! Construct from a base class object. CAtcStationList(const CSequence &other); - //! Find 0..n stations by callsign - CAtcStationList findByCallsign(const CCallsign &callsign) const; - - //! Find 0..n stations matching any of a set of callsigns - CAtcStationList findByCallsigns(const CCallsignList &callsigns) const; - - //! Find first station by callsign, if not return given value / default - CAtcStation findFirstByCallsign(const CCallsign &callsign, const CAtcStation &ifNotFound = CAtcStation()) const; - - //! Find 0..n stations within range of given coordinate - CAtcStationList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; - //! Find 0..n stations tune in frequency of COM unit (with 25kHt channel spacing CAtcStationList findIfComUnitTunedIn25KHz(const BlackMisc::Aviation::CComSystem &comUnit) const; - //! Find 0..n stations matching the suffix (e.g. TWR) - CAtcStationList findBySuffix(const QString &suffix) const; - //! All controllers (with valid data) BlackMisc::Network::CUserList getControllers() const; - //! Get all (different suffixes) - QMap getSuffixes() const; - - //! Update distances to coordinate, usually own aircraft's position - void calculateDistancesToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); - //! Merge with ATC station representing booking information. //! Both sides (booking, online station) will be updated. //! \remarks Can be used if the stored data in this list are online ATC stations @@ -78,6 +63,13 @@ namespace BlackMisc //! Register metadata static void registerMetadata(); + protected: + //! Myself + virtual const CAtcStationList &getContainer() const { return *this; } + + //! Myself + virtual CAtcStationList &getContainer() { return *this; } + }; } //namespace diff --git a/src/blackmisc/avcallsignobjectlist.cpp b/src/blackmisc/avcallsignobjectlist.cpp new file mode 100644 index 000000000..ed4a6aef0 --- /dev/null +++ b/src/blackmisc/avcallsignobjectlist.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2015 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "blackmisc/avcallsignobjectlist.h" +#include "blackmisc/predicates.h" +#include "blackmisc/avatcstationlist.h" +#include "blackmisc/avaircraftlist.h" +#include "blackmisc/avaircraftsituationlist.h" +#include "blackmisc/simulation/simulatedaircraftlist.h" + +namespace BlackMisc +{ + namespace Aviation + { + template + ICallsignObjectList::ICallsignObjectList() + { } + + template + bool ICallsignObjectList::containsCallsign(const CCallsign &callsign) const + { + return this->getContainer().contains(&OBJ::getCallsign, callsign); + } + + template + int ICallsignObjectList::applyIfCallsign(const CCallsign &callsign, const CPropertyIndexVariantMap &variantMap) + { + return this->getContainer().applyIf(&OBJ::getCallsign, callsign, variantMap); + } + + template + CONTAINER ICallsignObjectList::findByCallsign(const CCallsign &callsign) const + { + return this->getContainer().findBy(&OBJ::getCallsign, callsign); + } + + template + CONTAINER ICallsignObjectList::findByCallsigns(const CCallsignList &callsigns) const + { + return this->getContainer().findBy(Predicates::MemberIsAnyOf(&OBJ::getCallsign, callsigns)); + } + + template + OBJ ICallsignObjectList::findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound) const + { + return this->findByCallsign(callsign).frontOrDefault(ifNotFound); + } + + template + OBJ ICallsignObjectList::findBackByCallsign(const CCallsign &callsign, const OBJ &ifNotFound) const + { + return this->findByCallsign(callsign).backOrDefault(ifNotFound); + } + + template + CONTAINER ICallsignObjectList::findBySuffix(const QString &suffix) const + { + CONTAINER r; + if (suffix.isEmpty()) { return r; } + QString sfxUpper(suffix.trimmed().toUpper()); + r = this->getContainer().findBy([ = ](const OBJ & csObj) -> bool + { + return (csObj.getCallsign().getSuffix() == sfxUpper); + }); + return r; + } + + template + QMap ICallsignObjectList::getSuffixes() const + { + QMap r; + for (const OBJ &csObj : this->getContainer()) + { + const QString s = csObj.getCallsign().getSuffix(); + if (s.isEmpty()) { continue; } + if (r.contains(s)) + { + r[s] = r[s] + 1; + } + else + { + r.insert(s, 1); + } + } + return r; + } + + template + int ICallsignObjectList::incrementalUpdateOrAdd(const OBJ &objectBeforeChanges, const CPropertyIndexVariantMap &changedValues) + { + int c; + const CCallsign cs = objectBeforeChanges.getCallsign(); + if (this->containsCallsign(cs)) + { + if (changedValues.isEmpty()) { return 0; } + c = this->getContainer().applyIf(&OBJ::getCallsign, cs, changedValues); + } + else + { + c = 1; + if (changedValues.isEmpty()) + { + this->getContainer().push_back(objectBeforeChanges); + } + else + { + OBJ objectAdded(objectBeforeChanges); + objectAdded.apply(changedValues); + this->getContainer().push_back(objectAdded); + } + } + return c; + } + + // see here for the reason of thess forward instantiations + // http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html + template class ICallsignObjectList; + template class ICallsignObjectList; + template class ICallsignObjectList; + template class ICallsignObjectList; + + } // namespace +} // namespace + diff --git a/src/blackmisc/avcallsignobjectlist.h b/src/blackmisc/avcallsignobjectlist.h new file mode 100644 index 000000000..193159b10 --- /dev/null +++ b/src/blackmisc/avcallsignobjectlist.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_CALLSIGNOBJECTLIST_H +#define BLACKMISC_CALLSIGNOBJECTLIST_H + +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include "blackmisc/avcallsignlist.h" +#include "blackmisc/propertyindexlist.h" +#include "blackmisc/propertyindexvariantmap.h" +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + //! List of objects with callsign. + template + class ICallsignObjectList + { + public: + + //! Contains callsign? + bool containsCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; + + //! Apply for given callsign + int applyIfCallsign(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &variantMap); + + //! Find 0..n stations by callsign + CONTAINER findByCallsign(const CCallsign &callsign) const; + + //! Find 0..n aircraft matching any of a set of callsigns + CONTAINER findByCallsigns(const CCallsignList &callsigns) const; + + //! Find the first aircraft by callsign, if none return given one + OBJ findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound = {}) const; + + //! Find the back object by callsign, if none return given one + OBJ findBackByCallsign(const CCallsign &callsign, const OBJ &ifNotFound = {}) const; + + //! All with given suffix, empty suffixes ignored + CONTAINER findBySuffix(const QString &suffix) const; + + //! All suffixes with their respective count + QMap getSuffixes() const; + + //! Incremental update or add object + int incrementalUpdateOrAdd(const OBJ &objectBeforeChanged, const BlackMisc::CPropertyIndexVariantMap &changedValues); + + protected: + //! Constructor + ICallsignObjectList(); + + //! Container + virtual const CONTAINER &getContainer() const = 0; + + //! Container + virtual CONTAINER &getContainer() = 0; + }; + + } //namespace +} // namespace + +#endif //guard diff --git a/src/blackmisc/coordinategeodetic.cpp b/src/blackmisc/coordinategeodetic.cpp index 95ba3b831..604dd0a6a 100644 --- a/src/blackmisc/coordinategeodetic.cpp +++ b/src/blackmisc/coordinategeodetic.cpp @@ -22,18 +22,12 @@ namespace BlackMisc namespace Geo { - /* - * String for converter - */ QString CCoordinateGeodetic::convertToQString(bool i18n) const { QString s = "Geodetic: {%1, %2, %3}"; return s.arg(this->m_latitude.valueRoundedWithUnit(6, i18n)).arg(this->m_longitude.valueRoundedWithUnit(6, i18n)).arg(this->m_geodeticHeight.valueRoundedWithUnit(6, i18n)); } - /* - * From WGS84 coordinates - */ CCoordinateGeodetic CCoordinateGeodetic::fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const CLength &geodeticHeight) { CLatitude lat = CLatitude::fromWgs84(latitudeWgs84); @@ -41,10 +35,7 @@ namespace BlackMisc return CCoordinateGeodetic(lat, lon, geodeticHeight); } - /* - * Great circle distance - */ - PhysicalQuantities::CLength greatCircleDistance(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) + PhysicalQuantities::CLength calculateGreatCircleDistance(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) { // same coordinate results in 0 distance if (coordinate1.latitude() == coordinate2.latitude() && coordinate1.longitude() == coordinate2.longitude()) @@ -70,7 +61,7 @@ namespace BlackMisc return CLength(distance, CLengthUnit::m()); } - PhysicalQuantities::CAngle initialBearing(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) + PhysicalQuantities::CAngle calculateBearing(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) { // same coordinate results in 0 distance if (coordinate1.latitude() == coordinate2.latitude() && coordinate1.longitude() == coordinate2.longitude()) @@ -93,25 +84,16 @@ namespace BlackMisc return CAngle(bearing, CAngleUnit::deg()); } - /* - * Great circle distance - */ - CLength ICoordinateGeodetic::greatCircleDistance(const ICoordinateGeodetic &otherCoordinate) const + CLength ICoordinateGeodetic::calculateGreatCircleDistance(const ICoordinateGeodetic &otherCoordinate) const { - return Geo::greatCircleDistance((*this), otherCoordinate); + return Geo::calculateGreatCircleDistance((*this), otherCoordinate); } - /* - * Initial bearing - */ - CAngle ICoordinateGeodetic::initialBearing(const ICoordinateGeodetic &otherCoordinate) const + CAngle ICoordinateGeodetic::bearing(const ICoordinateGeodetic &otherCoordinate) const { - return Geo::initialBearing((*this), otherCoordinate); + return Geo::calculateBearing((*this), otherCoordinate); } - /* - * Property by index - */ CVariant ICoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (!index.isMyself()) @@ -127,49 +109,33 @@ namespace BlackMisc return CVariant(this->latitudeAsString()); case IndexLongitudeAsString: return CVariant(this->longitudeAsString()); + case IndexGeodeticHeight: + return this->geodeticHeight().propertyByIndex(index.copyFrontRemoved()); + case IndexGeodeticHeightAsString: + return CVariant(this->geodeticHeightAsString()); default: break; } } - Q_ASSERT_X(false, "ICoordinateGeodetic", "index unknown"); - QString m = QString("no property, index ").append(index.toQString()); + const QString m = QString("no property, index ").append(index.toQString()); + Q_ASSERT_X(false, "ICoordinateGeodetic", m.toLocal8Bit().constData()); return CVariant::fromValue(m); } - /* - * Property by index - */ CVariant CCoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return this->toCVariant(); } - ColumnIndex i = index.frontCasted(); - switch (i) + if (ICoordinateGeodetic::canHandleIndex(index)) { - case IndexLatitude: - return this->m_latitude.propertyByIndex(index.copyFrontRemoved()); - case IndexLatitudeAsString: - return CVariant(this->m_latitude.toQString()); - case IndexLongitude: - return this->m_longitude.propertyByIndex(index.copyFrontRemoved()); - case IndexLongitudeAsString: - return CVariant(this->m_longitude.toQString()); - case IndexGeodeticHeight: - return this->m_geodeticHeight.propertyByIndex(index.copyFrontRemoved()); - case IndexGeodeticHeightAsString: - return CVariant(this->m_geodeticHeight.toQString()); - default: - if (ICoordinateGeodetic::canHandleIndex(index)) - { - return ICoordinateGeodetic::propertyByIndex(index); - } - return CValueObject::propertyByIndex(index); + return ICoordinateGeodetic::propertyByIndex(index); + } + else + { + return CValueObject::propertyByIndex(index.copyFrontRemoved()); } } - /* - * Set property as index - */ void CCoordinateGeodetic::setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index) { if (index.isMyself()) @@ -177,17 +143,17 @@ namespace BlackMisc this->convertFromCVariant(variant); return; } - ColumnIndex i = index.frontCasted(); + ICoordinateGeodetic::ColumnIndex i = index.frontCasted(); switch (i) { case IndexGeodeticHeight: - this->setGeodeticHeight(variant.value()); + this->m_geodeticHeight.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexLatitude: - this->setLatitude(variant.value()); + this->m_latitude.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexLongitude: - this->setLongitude(variant.value()); + this->m_longitude.setPropertyByIndex(variant, index.copyFrontRemoved()); break; case IndexLatitudeAsString: this->setLatitude(CLatitude::fromWgs84(variant.toQString())); @@ -203,5 +169,37 @@ namespace BlackMisc break; } } + + CCoordinateGeodetic &CCoordinateGeodetic::switchUnit(const CAngleUnit &unit) + { + this->m_latitude.switchUnit(unit); + this->m_longitude.switchUnit(unit); + return *this; + } + + CCoordinateGeodetic &CCoordinateGeodetic::switchUnit(const CLengthUnit &unit) + { + this->m_geodeticHeight.switchUnit(unit); + return *this; + } + + CLength ICoordinateWithRelativePosition::calculcateDistanceToOwnAircraft(const ICoordinateGeodetic &position, bool updateValues) + { + if (!updateValues) { return Geo::calculateGreatCircleDistance(*this, position); } + this->m_distanceToOwnAircraft = Geo::calculateGreatCircleDistance(*this, position); + return this->m_distanceToOwnAircraft; + } + + CLength ICoordinateWithRelativePosition::calculcateDistanceAndBearingToOwnAircraft(const ICoordinateGeodetic &position, bool updateValues) + { + if (!updateValues) { return Geo::calculateGreatCircleDistance(*this, position); } + this->m_distanceToOwnAircraft = Geo::calculateGreatCircleDistance(*this, position); + this->m_bearingToOwnAircraft = Geo::calculateBearing(*this, position); + return this->m_distanceToOwnAircraft; + } + + ICoordinateWithRelativePosition::ICoordinateWithRelativePosition() + { } + } // namespace } // namespace diff --git a/src/blackmisc/coordinategeodetic.h b/src/blackmisc/coordinategeodetic.h index 77b3ac952..50b3c1a7c 100644 --- a/src/blackmisc/coordinategeodetic.h +++ b/src/blackmisc/coordinategeodetic.h @@ -23,10 +23,10 @@ namespace BlackMisc namespace Geo { - /*! - * Latitude and longitude interface - * Interface for geodetic ccordinates - */ + //! Geodetic coordinate + //! \sa http://www.esri.com/news/arcuser/0703/geoid1of3.html + //! \sa http://http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf (page 5) + //! \sa http://en.wikipedia.org/wiki/Geodetic_datum#Vertical_datum class ICoordinateGeodetic { public: @@ -36,7 +36,9 @@ namespace BlackMisc IndexLatitude = BlackMisc::CPropertyIndex::GlobalIndexICoordinateGeodetic, IndexLongitude, IndexLatitudeAsString, - IndexLongitudeAsString + IndexLongitudeAsString, + IndexGeodeticHeight, + IndexGeodeticHeightAsString }; //! Destructor @@ -48,6 +50,12 @@ namespace BlackMisc //! Longitude virtual const CLongitude &longitude() const = 0; + //! Height, ellipsoidal or geodetic height (used in GPS) + //! This is approximately MSL (orthometric) height, aka elevation. + //! \sa see http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf page 5 + //! \sa http://www.esri.com/news/arcuser/0703/geoid1of3.html + virtual const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const = 0; + //! \copydoc CValueObject::propertyByIndex virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -57,47 +65,70 @@ namespace BlackMisc //! Longitude as string QString longitudeAsString() const { return this->longitude().toQString(true); } + //! Height as string + QString geodeticHeightAsString() const { return this->geodeticHeight().toQString(true); } + //! Great circle distance - BlackMisc::PhysicalQuantities::CLength greatCircleDistance(const ICoordinateGeodetic &otherCoordinate) const; + BlackMisc::PhysicalQuantities::CLength calculateGreatCircleDistance(const ICoordinateGeodetic &otherCoordinate) const; //! Initial bearing - BlackMisc::PhysicalQuantities::CAngle initialBearing(const ICoordinateGeodetic &otherCoordinate) const; + BlackMisc::PhysicalQuantities::CAngle bearing(const ICoordinateGeodetic &otherCoordinate) const; //! Can given index be handled static bool canHandleIndex(const BlackMisc::CPropertyIndex &index) { int i = index.frontCasted(); - return (i >= static_cast(IndexLatitude)) && (i <= static_cast(IndexLongitudeAsString)); + return (i >= static_cast(IndexLatitude)) && (i <= static_cast(IndexGeodeticHeightAsString)); } }; //! Great circle distance between points - BlackMisc::PhysicalQuantities::CLength greatCircleDistance(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2); + BlackMisc::PhysicalQuantities::CLength calculateGreatCircleDistance(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2); //! Initial bearing - BlackMisc::PhysicalQuantities::CAngle initialBearing(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2); + BlackMisc::PhysicalQuantities::CAngle calculateBearing(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2); - //! Geodetic coordinate - //! \sa http://www.esri.com/news/arcuser/0703/geoid1of3.html - //! \sa http://http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf (page 5) - //! \sa http://en.wikipedia.org/wiki/Geodetic_datum#Vertical_datum - class CCoordinateGeodetic : public CValueObjectStdTuple, public ICoordinateGeodetic + //! Interface (actually more an abstract class) of coordinate and + //! relative position to own aircraft + class ICoordinateWithRelativePosition : public ICoordinateGeodetic { public: - //! Properties by index - enum ColumnIndex - { - IndexLatitude = BlackMisc::CPropertyIndex::GlobalIndexCCoordinateGeodetic, - IndexLongitude, - IndexLatitudeAsString, - IndexLongitudeAsString, - IndexGeodeticHeight, - IndexGeodeticHeightAsString - }; + //! Get the distance to own plane + const BlackMisc::PhysicalQuantities::CLength &getDistanceToOwnAircraft() const { return m_distanceToOwnAircraft; } + + //! Set distance to own plane + void setDistanceToOwnAircraft(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToOwnAircraft = distance; } + + //! Get the bearing to own plane + const BlackMisc::PhysicalQuantities::CAngle &getBearingToOwnAIrcraft() const { return m_bearingToOwnAircraft; } + + //! Set bearing to own plane + void setBearingToOwnAircraft(const BlackMisc::PhysicalQuantities::CAngle &angle) { this->m_bearingToOwnAircraft = angle; } + + //! Valid distance? + bool hasValidDistance() const { return !this->m_distanceToOwnAircraft.isNull();} + + //! Valid bearing? + bool hasValidBearing() const { return !this->m_bearingToOwnAircraft.isNull();} + + //! Calculcate distance, set it, and return distance + BlackMisc::PhysicalQuantities::CLength calculcateDistanceToOwnAircraft(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues = true); + + //! Calculcate distance and bearing to plane, set it, and return distance + BlackMisc::PhysicalQuantities::CLength calculcateDistanceAndBearingToOwnAircraft(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues = true); protected: - //! \copydoc CValueObject::convertToQString - virtual QString convertToQString(bool i18n = false) const override; + //! Constructor + ICoordinateWithRelativePosition(); + + BlackMisc::PhysicalQuantities::CAngle m_bearingToOwnAircraft; //!< temporary stored value + BlackMisc::PhysicalQuantities::CLength m_distanceToOwnAircraft; //!< temporary stored value + }; + + + //! Geodetic coordinate + class CCoordinateGeodetic : public CValueObjectStdTuple, public ICoordinateGeodetic + { public: //! Default constructor @@ -117,11 +148,8 @@ namespace BlackMisc //! \copydoc ICoordinateGeodetic::longitude virtual const CLongitude &longitude() const override { return this->m_longitude; } - //! Height, ellipsoidal or geodetic height (used in GPS) - //! This is approximately MSL (orthometric) height, aka elevation. - //! \sa see http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf page 5 - //! \sa http://www.esri.com/news/arcuser/0703/geoid1of3.html - const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const { return this->m_geodeticHeight; } + //! \copydoc ICoordinateGeodetic::geodeticHeight + virtual const BlackMisc::PhysicalQuantities::CLength &geodeticHeight() const override { return this->m_geodeticHeight; } //! \copydoc CValueObject::propertyByIndex virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override; @@ -130,19 +158,10 @@ namespace BlackMisc virtual void setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index) override; //! Switch unit of latitude / longitude - CCoordinateGeodetic &switchUnit(const BlackMisc::PhysicalQuantities::CAngleUnit &unit) - { - this->m_latitude.switchUnit(unit); - this->m_longitude.switchUnit(unit); - return *this; - } + CCoordinateGeodetic &switchUnit(const BlackMisc::PhysicalQuantities::CAngleUnit &unit); //! Switch unit of height - CCoordinateGeodetic &switchUnit(const BlackMisc::PhysicalQuantities::CLengthUnit &unit) - { - this->m_geodeticHeight.switchUnit(unit); - return *this; - } + CCoordinateGeodetic &switchUnit(const BlackMisc::PhysicalQuantities::CLengthUnit &unit); //! Set latitude void setLatitude(const CLatitude &latitude) { this->m_latitude = latitude; } @@ -156,15 +175,19 @@ namespace BlackMisc //! Coordinate by WGS84 position data static CCoordinateGeodetic fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const BlackMisc::PhysicalQuantities::CLength &geodeticHeight = {}); + protected: + //! \copydoc CValueObject::convertToQString + virtual QString convertToQString(bool i18n = false) const override; + private: BLACK_ENABLE_TUPLE_CONVERSION(CCoordinateGeodetic) - BlackMisc::Geo::CLatitude m_latitude; //!< Latitude + BlackMisc::Geo::CLatitude m_latitude; //!< Latitude BlackMisc::Geo::CLongitude m_longitude; //!< Longitude BlackMisc::PhysicalQuantities::CLength m_geodeticHeight; //!< height, ellipsoidal or geodetic height }; - } -} + } // namespace +} // namespace BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Geo::CCoordinateGeodetic, (o.m_latitude, o.m_longitude, o.m_geodeticHeight)) Q_DECLARE_METATYPE(BlackMisc::Geo::CCoordinateGeodetic) diff --git a/src/blackmisc/geoobjectlist.cpp b/src/blackmisc/geoobjectlist.cpp new file mode 100644 index 000000000..f04d824e8 --- /dev/null +++ b/src/blackmisc/geoobjectlist.cpp @@ -0,0 +1,83 @@ +/* Copyright (C) 2015 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "blackmisc/geoobjectlist.h" +#include "blackmisc/predicates.h" +#include "blackmisc/avatcstationlist.h" +#include "blackmisc/avaircraftlist.h" +#include "blackmisc/avairportlist.h" +#include "blackmisc/simulation/simulatedaircraftlist.h" + +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackMisc +{ + namespace Geo + { + template + IGeoObjectList::IGeoObjectList() + { } + + template + IGeoObjectWithRelativePositionList::IGeoObjectWithRelativePositionList() + { } + + template + CONTAINER IGeoObjectList::findWithinRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const + { + return this->getContainer().findBy([&](const OBJ & geoObj) + { + return calculateGreatCircleDistance(geoObj, coordinate) <= range; + }); + } + + template + void IGeoObjectWithRelativePositionList::calculcateDistanceAndBearingToPlane(const ICoordinateGeodetic &position) + { + for (OBJ &geoObj : this->getContainer()) + { + geoObj.calculcateDistanceAndBearingToOwnAircraft(position); + } + } + + template + void IGeoObjectWithRelativePositionList::removeIfOutsideRange(const Geo::ICoordinateGeodetic &position, const CLength &maxDistance, bool updateValues) + { + this->getContainer().removeIf([ & ](OBJ & geoObj) + { + return geoObj.calculcateDistanceAndBearingToOwnAircraft(position, updateValues) > maxDistance; + }); + } + + template + void IGeoObjectWithRelativePositionList::sortByRange(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues) + { + if (updateValues) + { + this->calculcateDistanceAndBearingToPlane(position); + } + this->getContainer().sort([ & ](const OBJ & a, const OBJ & b) { return a.getDistanceToOwnAircraft() < b.getDistanceToOwnAircraft(); }); + } + + + // see here for the reason of thess forward instantiations + // http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html + template class IGeoObjectList; + template class IGeoObjectList; + template class IGeoObjectList; + template class IGeoObjectList; + + template class IGeoObjectWithRelativePositionList; + template class IGeoObjectWithRelativePositionList; + template class IGeoObjectWithRelativePositionList; + template class IGeoObjectWithRelativePositionList; + + } // namespace +} // namespace + diff --git a/src/blackmisc/geoobjectlist.h b/src/blackmisc/geoobjectlist.h new file mode 100644 index 000000000..917da6073 --- /dev/null +++ b/src/blackmisc/geoobjectlist.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_GEOOBJECTLIST_H +#define BLACKMISC_GEOOBJECTLIST_H + +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include "blackmisc/coordinategeodetic.h" + +namespace BlackMisc +{ + namespace Geo + { + //! List of objects with geo coordinates. + template + class IGeoObjectList + { + public: + + /*! + * Find 0..n objects within range of given coordinate + * \param coordinate other position + * \param range within range of other position + * \return + */ + CONTAINER findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; + + protected: + //! Constructor + IGeoObjectList(); + + //! Container + virtual const CONTAINER &getContainer() const = 0; + + //! Container + virtual CONTAINER &getContainer() = 0; + }; + + //! List of objects with geo coordinates. + template + class IGeoObjectWithRelativePositionList : public IGeoObjectList + { + public: + //! Calculate distances, then sort by range + void sortByRange(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues); + + //! Calculate distances, remove if outside range + void removeIfOutsideRange(const BlackMisc::Geo::ICoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &maxDistance, bool updateValues); + + //! Calculate distances + void calculcateDistanceAndBearingToPlane(const BlackMisc::Geo::ICoordinateGeodetic &position); + + protected: + //! Constructor + IGeoObjectWithRelativePositionList(); + + }; + + } //namespace +} // namespace + +#endif //guard diff --git a/src/blackmisc/propertyindex.h b/src/blackmisc/propertyindex.h index f57796e02..8a5840054 100644 --- a/src/blackmisc/propertyindex.h +++ b/src/blackmisc/propertyindex.h @@ -37,6 +37,7 @@ namespace BlackMisc GlobalIndexCPhysicalQuantity = 100, GlobalIndexCStatusMessage = 200, GlobalIndexCNameVariantPair = 300, + GlobalIndexTimestampBased = 400, GlobalIndexCCallsign = 1000, GlobalIndexCAircraftIcao = 1100, GlobalIndexCAircraft = 1200, diff --git a/src/blackmisc/simulation/simulatedaircraftlist.cpp b/src/blackmisc/simulation/simulatedaircraftlist.cpp index 8a6d3f0f3..245b0eb02 100644 --- a/src/blackmisc/simulation/simulatedaircraftlist.cpp +++ b/src/blackmisc/simulation/simulatedaircraftlist.cpp @@ -47,64 +47,6 @@ namespace BlackMisc registerMetaValueType(); } - /* - * Find by callsign - */ - CSimulatedAircraftList CSimulatedAircraftList::findByCallsign(const CCallsign &callsign) const - { - return this->findBy(&CSimulatedAircraft::getCallsign, callsign); - } - - /* - * Find by callsigns - */ - CSimulatedAircraftList CSimulatedAircraftList::findByCallsigns(const CCallsignList &callsigns) const - { - return this->findBy(Predicates::MemberIsAnyOf(&CSimulatedAircraft::getCallsign, callsigns)); - } - - /* - * Find by callsign - */ - CSimulatedAircraft CSimulatedAircraftList::findFirstByCallsign(const CCallsign &callsign, const CSimulatedAircraft &ifNotFound) const - { - return this->findByCallsign(callsign).frontOrDefault(ifNotFound); - } - - /* - * Contains callsign? - */ - bool CSimulatedAircraftList::containsCallsign(const CCallsign &callsign) const - { - return this->contains(&CSimulatedAircraft::getCallsign, callsign); - } - - int CSimulatedAircraftList::incrementalUpdateOrAdd(const CSimulatedAircraft &toChangeAircraft, const CPropertyIndexVariantMap &changedValues) - { - int c; - const CCallsign cs = toChangeAircraft.getCallsign(); - if (this->containsCallsign(cs)) - { - if (changedValues.isEmpty()) { return 0; } - c = this->applyIf(&CSimulatedAircraft::getCallsign, cs, changedValues); - } - else - { - c = 1; - if (changedValues.isEmpty()) - { - this->push_back(toChangeAircraft); - } - else - { - CSimulatedAircraft addAircraft(toChangeAircraft); - addAircraft.apply(changedValues); - this->push_back(addAircraft); - } - } - return c; - } - /* * All pilots */ @@ -113,16 +55,5 @@ namespace BlackMisc return this->findBy(Predicates::MemberValid(&CSimulatedAircraft::getPilot)).transform(Predicates::MemberTransform(&CSimulatedAircraft::getPilot)); } - /* - * Aircrafts within range - */ - CSimulatedAircraftList CSimulatedAircraftList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const - { - return this->findBy([&](const CSimulatedAircraft & aircraft) - { - return BlackMisc::Geo::greatCircleDistance(aircraft, coordinate) <= range; - }); - } - } // namespace } // namespace diff --git a/src/blackmisc/simulation/simulatedaircraftlist.h b/src/blackmisc/simulation/simulatedaircraftlist.h index 29f4c91de..1502d1a99 100644 --- a/src/blackmisc/simulation/simulatedaircraftlist.h +++ b/src/blackmisc/simulation/simulatedaircraftlist.h @@ -13,7 +13,8 @@ #define BLACKMISC_SIMULATEDNAIRCRAFTLIST_H #include "blackmisc/simulation/simulatedaircraft.h" -#include "blackmisc/avcallsignlist.h" +#include "blackmisc/avcallsignobjectlist.h" +#include "blackmisc/geoobjectlist.h" #include "blackmisc/nwuserlist.h" #include "blackmisc/collection.h" #include "blackmisc/sequence.h" @@ -26,7 +27,10 @@ namespace BlackMisc namespace Simulation { //! Value object encapsulating a list of aircraft. - class CSimulatedAircraftList : public CSequence + class CSimulatedAircraftList : + public BlackMisc::CSequence, + public BlackMisc::Aviation::ICallsignObjectList, + public BlackMisc::Geo::IGeoObjectList { public: //! Default constructor. @@ -35,32 +39,9 @@ namespace BlackMisc //! Construct from a base class object. CSimulatedAircraftList(const CSequence &other); - //! Find 0..n stations by callsign - CSimulatedAircraftList findByCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; - - //! Find 0..n aircraft matching any of a set of callsigns - CSimulatedAircraftList findByCallsigns(const BlackMisc::Aviation::CCallsignList &callsigns) const; - - //! Find the first aircraft by callsign, if none return given one - CSimulatedAircraft findFirstByCallsign(const BlackMisc::Aviation::CCallsign &callsign, const CSimulatedAircraft &ifNotFound = CSimulatedAircraft()) const; - - //! Contains callsign? - bool containsCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; - - //! Incremental update or add aircraft - int incrementalUpdateOrAdd(const BlackMisc::Simulation::CSimulatedAircraft &toChangeAircraft, const BlackMisc::CPropertyIndexVariantMap &changedValues); - //! All pilots (with valid data) BlackMisc::Network::CUserList getPilots() const; - /*! - * Find 0..n stations within range of given coordinate - * \param coordinate other position - * \param range within range of other position - * \return - */ - CSimulatedAircraftList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; - //! \copydoc CValueObject::toQVariant virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); } @@ -69,6 +50,14 @@ namespace BlackMisc //! Register metadata static void registerMetadata(); + + protected: + //! Myself + virtual const CSimulatedAircraftList &getContainer() const { return *this; } + + //! Myself + virtual CSimulatedAircraftList &getContainer() { return *this; } + }; } //namespace diff --git a/src/blackmisc/testing.cpp b/src/blackmisc/testing.cpp index 93bf2ad90..f9fdecae2 100644 --- a/src/blackmisc/testing.cpp +++ b/src/blackmisc/testing.cpp @@ -55,7 +55,7 @@ namespace BlackMisc station.setPropertyByIndex(CVariant::from(false), CAtcStation::IndexIsOnline); station.setPropertyByIndex(CVariant::from(dtFrom), CAtcStation::IndexBookedFrom); station.setPropertyByIndex(CVariant::from(dtUntil), CAtcStation::IndexBookedUntil); - station.setPropertyByIndex(CLength(index + 1, CLengthUnit::NM()).toCVariant(), CAtcStation::IndexDistance); + station.setPropertyByIndex(CLength(index + 1, CLengthUnit::NM()).toCVariant(), CAtcStation::IndexDistanceToOwnAircraft); return station; } else @@ -63,7 +63,7 @@ namespace BlackMisc CAtcStation station(CCallsign(cs), user, CFrequency(f, CFrequencyUnit::MHz()), geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil); - station.setDistanceToPlane(CLength(index + 1, CLengthUnit::NM())); + station.setDistanceToOwnAircraft(CLength(index + 1, CLengthUnit::NM())); return station; } } @@ -85,7 +85,7 @@ namespace BlackMisc r.append(station.propertyByIndex({ CAtcStation::IndexController, CUser::IndexRealName}).toQString()); r.append(station.propertyByIndex({ CAtcStation::IndexPosition, CCoordinateGeodetic::IndexLatitudeAsString}).toQString()); r.append(station.propertyByIndex({ CAtcStation::IndexPosition, CCoordinateGeodetic::IndexLongitudeAsString}).toQString()); - r.append(station.propertyByIndex({ CAtcStation::IndexDistance, CLength::IndexValueRounded2DigitsWithUnit}).toQString()); + r.append(station.propertyByIndex({ CAtcStation::IndexDistanceToOwnAircraft, CLength::IndexValueRounded2DigitsWithUnit}).toQString()); r.append(station.propertyByIndex({ CAtcStation::IndexBookedFrom}).toDateTime().toString("YYYY-mm-dd hh:mm")); r.append(station.propertyByIndex({ CAtcStation::IndexBookedUntil}).toDateTime().toString("YYYY-mm-dd hh:mm")); } @@ -95,7 +95,7 @@ namespace BlackMisc r.append(station.getController().getRealName()); r.append(station.getPosition().latitudeAsString()); r.append(station.getPosition().longitudeAsString()); - r.append(station.getDistanceToPlane().toQString(true)); + r.append(station.getDistanceToOwnAircraft().toQString(true)); r.append(station.getBookedFromUtc().toString("YYYY-mm-dd hh:mm")); r.append(station.getBookedUntilUtc().toString("YYYY-mm-dd hh:mm")); } @@ -121,7 +121,7 @@ namespace BlackMisc for (int i = 0; i < n; i++) { int p = i % s; - atc.calculcateDistanceToPlane(pos.at(p)); + atc.calculcateDistanceToOwnAircraft(pos.at(p)); } } diff --git a/src/blackmisc/timestampbased.cpp b/src/blackmisc/timestampbased.cpp new file mode 100644 index 000000000..10713d385 --- /dev/null +++ b/src/blackmisc/timestampbased.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "timestampbased.h" +#include "variant.h" + +namespace BlackMisc +{ + + QDateTime ITimestampBased::getUtcTimestamp() const + { + return QDateTime::fromMSecsSinceEpoch(this->m_timestampMSecsSinceEpoch, Qt::UTC); + } + + QString ITimestampBased::getFormattedUtcTimestamp() const + { + return this->getUtcTimestamp().toString("dd hh:mm:ss"); + } + + void ITimestampBased::setUtcTimestamp(const QDateTime ×tamp) + { + this->m_timestampMSecsSinceEpoch = timestamp.toMSecsSinceEpoch(); + } + + bool ITimestampBased::isNewerThan(const ITimestampBased &otherTimestampObj) const + { + return this->m_timestampMSecsSinceEpoch > otherTimestampObj.m_timestampMSecsSinceEpoch; + } + + bool ITimestampBased::isNewerThan(qint64 mSecsSinceEpoch) const + { + return this->m_timestampMSecsSinceEpoch > mSecsSinceEpoch; + } + + bool ITimestampBased::isOlderThan(const ITimestampBased &otherTimestampObj) const + { + return this->m_timestampMSecsSinceEpoch < otherTimestampObj.m_timestampMSecsSinceEpoch; + } + + bool ITimestampBased::isOlderThan(qint64 mSecsSinceEpoch) const + { + return this->m_timestampMSecsSinceEpoch < mSecsSinceEpoch; + } + + bool ITimestampBased::isOlderThanNowMinusOffset(int offsetMs) const + { + if (offsetMs <= 0) { return false; } + return this->m_timestampMSecsSinceEpoch < (QDateTime::currentMSecsSinceEpoch() - offsetMs); + } + + bool ITimestampBased::isSame(const ITimestampBased &otherTimestampObj) const + { + return this->m_timestampMSecsSinceEpoch == otherTimestampObj.m_timestampMSecsSinceEpoch; + } + + qint64 ITimestampBased::msecsTo(const ITimestampBased &otherTimestampObj) const + { + return otherTimestampObj.m_timestampMSecsSinceEpoch - this->m_timestampMSecsSinceEpoch; + } + + qint64 ITimestampBased::msecsToAbs(const ITimestampBased &otherTimestampObj) const + { + qint64 dt = this->msecsTo(otherTimestampObj); + return dt > 0 ? dt : dt * -1; + } + + void ITimestampBased::setCurrentUtcTime() + { + this->m_timestampMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); + } + + CVariant ITimestampBased::propertyByIndex(const CPropertyIndex &index) const + { + if (!index.isEmpty()) + { + ColumnIndex i = index.frontCasted(); + switch (i) + { + case IndexUtcTimestamp: + return CVariant::fromValue(this->getUtcTimestamp()); + case IndexMSecsSinceEpoch: + return CVariant::fromValue(this->getMSecsSinceEpoch()); + case IndexUtcTimestampFormatted: + return CVariant::fromValue(this->getFormattedUtcTimestamp()); + } + } + const QString m = QString("Cannot handle index %1").arg(index.toQString()); + Q_ASSERT_X(false, "propertyByIndex", m.toLocal8Bit().constData()); + return CVariant::fromValue(m); + } + + void ITimestampBased::setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) + { + if (!index.isEmpty()) + { + ColumnIndex i = index.frontCasted(); + switch (i) + { + case IndexUtcTimestamp: + this->setUtcTimestamp(variant.toDateTime()); + return; + case IndexMSecsSinceEpoch: + this->setMSecsSinceEpoch(variant.toInt()); + return; + } + } + const QString m = QString("Cannot handle index %1").arg(index.toQString()); + Q_ASSERT_X(false, "setPropertyByIndex", m.toLocal8Bit().constData()); + } + +} // namespace diff --git a/src/blackmisc/timestampbased.h b/src/blackmisc/timestampbased.h new file mode 100644 index 000000000..5d5169923 --- /dev/null +++ b/src/blackmisc/timestampbased.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_TIMESTAMPBASED_H +#define BLACKMISC_TIMESTAMPBASED_H + +#include "propertyindex.h" +#include + +namespace BlackMisc +{ + + //! Entity with timestamp + class ITimestampBased + { + public: + //! Properties by index + enum ColumnIndex + { + IndexUtcTimestamp = BlackMisc::CPropertyIndex::GlobalIndexTimestampBased, + IndexUtcTimestampFormatted, + IndexMSecsSinceEpoch + }; + + //! Get timestamp + QDateTime getUtcTimestamp() const; + + //! Timestamp as ms value + qint64 getMSecsSinceEpoch() const { return m_timestampMSecsSinceEpoch; } + + //! Timestamp as ms value + void setMSecsSinceEpoch(qint64 mSecsSinceEpoch) { m_timestampMSecsSinceEpoch = mSecsSinceEpoch; } + + //! Formatted timestamp + QString getFormattedUtcTimestamp() const; + + //! Set timestamp + void setUtcTimestamp(const QDateTime ×tamp); + + //! Is this newer than other? + bool isNewerThan(const ITimestampBased &otherTimestampObj) const; + + //! Is newer than epoch value? + bool isNewerThan(qint64 mSecsSinceEpoch) const; + + //! Is this older than other? + bool isOlderThan(const ITimestampBased &otherTimestampObj) const; + + //! Is this older than other? + bool isOlderThan(qint64 mSecsSinceEpoch) const; + + //! Older than now-offset + bool isOlderThanNowMinusOffset(int offsetMs) const; + + //! Same timestamp + bool isSame(const ITimestampBased &otherTimestampObj) const; + + //! Time difference + qint64 msecsTo(const ITimestampBased &otherTimestampObj) const; + + //! Time difference + qint64 msecsToAbs(const ITimestampBased &otherTimestampObj) const; + + //! Set the current time as timestamp + void setCurrentUtcTime(); + + //! Can given index be handled + static bool canHandleIndex(const BlackMisc::CPropertyIndex &index) + { + int i = index.frontCasted(); + return (i >= static_cast(IndexUtcTimestamp)) && (i <= static_cast(IndexMSecsSinceEpoch)); + } + + protected: + //! \copydoc CValueObject::propertyByIndex + virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; + + //! \copydoc CValueObject::setPropertyByIndex + virtual void setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index); + + qint64 m_timestampMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); //!< timestamp value + }; + +} // namespace + + +#endif // guard diff --git a/src/blackmisc/timestampobjectlist.cpp b/src/blackmisc/timestampobjectlist.cpp new file mode 100644 index 000000000..300dd970a --- /dev/null +++ b/src/blackmisc/timestampobjectlist.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2015 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "blackmisc/timestampobjectlist.h" +#include "blackmisc/predicates.h" +#include "blackmisc/avaircraftsituationlist.h" +#include "blackmisc/aviation/aircraftpartslist.h" +#include +#include + +namespace BlackMisc +{ + template + ITimestampObjectList::ITimestampObjectList() + { } + + template + CONTAINER ITimestampObjectList::findBefore(qint64 msSinceEpoch) const + { + return this->getContainer().findBy([&](const OBJ & obj) + { + return obj.isOlderThan(msSinceEpoch); + }); + } + + template + CONTAINER ITimestampObjectList::findBefore(const QDateTime &dateTime) const + { + return this->findBefore(dateTime.toMSecsSinceEpoch()); + } + + template + CONTAINER ITimestampObjectList::findAfter(qint64 msSinceEpoc) const + { + return this->getContainer().findBy([&](const OBJ & obj) + { + return obj.isNewerThan(msSinceEpoc); + }); + } + + template + QList ITimestampObjectList::splitByTime(qint64 msSinceEpoch) const + { + CONTAINER newer(this->getContainer()); + newer.sortLatestFirst(); + CONTAINER older; + for (auto it = newer.begin(); it != newer.end(); ++it) + { + if (it->isOlderThan(msSinceEpoch)) + { + // better "move", ?? std::make_move_iterator + older.insert(CRange(it, newer.end())); + newer.erase(it, newer.end()); + break; + } + } + return QList({older, newer}); + } + + template + OBJ ITimestampObjectList::latestValue() const + { + if (this->getContainer().isEmpty()) { return OBJ(); } + CONTAINER container(getContainer()); // copy + container.sortLatestFirst(); + return container.front(); + } + + template + OBJ ITimestampObjectList::oldestValue() const + { + if (this->getContainer().isEmpty()) { return OBJ(); } + CONTAINER container(getContainer()); // copy + container.sortLatestFirst(); + return container.back(); + } + + template + CONTAINER ITimestampObjectList::findAfter(const QDateTime &dateTime) const + { + return this->findAfter(dateTime.toMSecsSinceEpoch()); + } + + template + void ITimestampObjectList::removeBefore(const QDateTime &dateTime) + { + this->removeBefore(dateTime.toMSecsSinceEpoch()); + } + + template + void ITimestampObjectList::removeBefore(qint64 msSinceEpoc) + { + this->getContainer().removeIf([&](const OBJ & obj) + { + return obj.isOlderThan(msSinceEpoc); + }); + } + + template + void ITimestampObjectList::removeOlderThanNowMinusOffset(int offsetMs) + { + const qint64 epoch = QDateTime::currentMSecsSinceEpoch() - offsetMs; + this->getContainer().removeIf([&](const OBJ & obj) + { + return obj.isOlderThan(epoch); + }); + } + + template + void ITimestampObjectList::sortLatestFirst() + { + this->getContainer().sortOldestFirst(); + std::reverse(this->getContainer().begin(), this->getContainer().end()); + } + + template + void ITimestampObjectList::sortOldestFirst() + { + this->getContainer().sort(BlackMisc::Predicates::MemberLess(&OBJ::getMSecsSinceEpoch)); + } + + // see here for the reason of thess forward instantiations + // http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html + template class ITimestampObjectList; + +} // namespace diff --git a/src/blackmisc/timestampobjectlist.h b/src/blackmisc/timestampobjectlist.h new file mode 100644 index 000000000..5a04ae02e --- /dev/null +++ b/src/blackmisc/timestampobjectlist.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_TIMESTAMPOBJECTLIST_H +#define BLACKMISC_TIMESTAMPOBJECTLIST_H + +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include +#include + +namespace BlackMisc +{ + //! List of objects with timestamp. + //! Such objects should implement \sa ITimestampBased + template + class ITimestampObjectList + { + public: + + //! List of objects before dateTime + CONTAINER findBefore(const QDateTime &dateTime) const; + + //! List of objects before msSinceEpoch + CONTAINER findBefore(qint64 msSinceEpoch) const; + + //! List of objects after dateTime + CONTAINER findAfter(const QDateTime &dateTime) const; + + //! List of objects after msSinceEpoch + CONTAINER findAfter(qint64 msSinceEpoch) const; + + //! Split into 2 containers, [0] >= msSinceEpoch [b] < msSinceEpoch + QList splitByTime(qint64 msSinceEpoch) const; + + //! Latest value + OBJ latestValue() const; + + //! Latest value + OBJ oldestValue() const; + + //! Remove objects with timestamp before dateTime + void removeBefore(const QDateTime &dateTime); + + //! Remove objects with timestamp before dateTime + void removeBefore(qint64 msSinceEpoch); + + //! Remove objects older than seconds + void removeOlderThanNowMinusOffset(int offsetMs); + + //! Sort by timestamp + void sortLatestFirst(); + + //! Sort by timestamp + void sortOldestFirst(); + + protected: + //! Constructor + ITimestampObjectList(); + + //! Container + virtual const CONTAINER &getContainer() const = 0; + + //! Container + virtual CONTAINER &getContainer() = 0; + }; + +} //namespace + +#endif //guard diff --git a/src/plugins/simulator/fs9/blacksimplugin_freefunctions.cpp b/src/plugins/simulator/fs9/blacksimplugin_freefunctions.cpp index f1121b0aa..d0de02dd0 100644 --- a/src/plugins/simulator/fs9/blacksimplugin_freefunctions.cpp +++ b/src/plugins/simulator/fs9/blacksimplugin_freefunctions.cpp @@ -118,13 +118,13 @@ namespace BlackSimPlugin // We want the distance in Latitude direction. Longitude must be equal for old and new position. helperPosition.setLatitude(newPosition.latitude()); helperPosition.setLongitude(oldPosition.longitude()); - CLength distanceLatitudeObj = greatCircleDistance(oldPosition, helperPosition); + CLength distanceLatitudeObj = calculateGreatCircleDistance(oldPosition, helperPosition); // Now we want the Longitude distance. Latitude must be equal for old and new position. helperPosition.setLatitude(oldPosition.latitude()); helperPosition.setLongitude(newSituation.longitude()); - CLength distanceLongitudeObj = greatCircleDistance(oldPosition, helperPosition); + CLength distanceLongitudeObj = calculateGreatCircleDistance(oldPosition, helperPosition); // Latitude and Longitude velocity positionVelocity.lat_velocity = distanceLatitudeObj.value(CLengthUnit::ft()) * 65536.0 / updateInterval; diff --git a/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp b/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp index 60d66ec19..5c8d5c8ec 100644 --- a/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp @@ -173,7 +173,7 @@ namespace BlackSimPlugin if (!CAirportIcao::isValidIcaoDesignator(icao)) continue; // tiny airfields in SIM CCoordinateGeodetic pos(pFacilityAirport->Latitude, pFacilityAirport->Longitude, pFacilityAirport->Altitude); CAirport airport(CAirportIcao(icao), pos); - CLength d = airport.calculcateDistanceAndBearingToPlane(posAircraft); + CLength d = airport.calculcateDistanceAndBearingToOwnAircraft(posAircraft); if (d > maxDistance) continue; simulatorFsx->m_airportsInRange.replaceOrAddByIcao(airport); } diff --git a/src/plugins/simulator/xplane/simulator_xplane.cpp b/src/plugins/simulator/xplane/simulator_xplane.cpp index ca852497e..f5568507e 100644 --- a/src/plugins/simulator/xplane/simulator_xplane.cpp +++ b/src/plugins/simulator/xplane/simulator_xplane.cpp @@ -7,6 +7,7 @@ #include "xbus_service_proxy.h" #include "xbus_traffic_proxy.h" #include "blackmisc/logmessage.h" +#include "blackmisc/coordinategeodetic.h" #include #include @@ -15,6 +16,7 @@ using namespace BlackMisc::Aviation; using namespace BlackMisc::Network; using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Simulation; +using namespace BlackMisc::Geo; namespace BlackSimPlugin { @@ -254,7 +256,8 @@ namespace BlackSimPlugin BlackMisc::Aviation::CAirportList CSimulatorXPlane::getAirportsInRange() const { auto copy = m_airports; - copy.sortByRange({ m_xplaneData.latitude, m_xplaneData.longitude, 0 }, true); + //! \todo Check if units match, xPlaneData has now hints what the values are + copy.sortByRange(CCoordinateGeodetic(m_xplaneData.latitude, m_xplaneData.longitude, 0), true); copy.truncate(20); return copy; } diff --git a/src/plugins/simulator/xplane/simulator_xplane.h b/src/plugins/simulator/xplane/simulator_xplane.h index 4b5257482..b7bb0eb04 100644 --- a/src/plugins/simulator/xplane/simulator_xplane.h +++ b/src/plugins/simulator/xplane/simulator_xplane.h @@ -130,6 +130,7 @@ namespace BlackSimPlugin BlackMisc::Aviation::CAirportList m_airports; BlackMisc::Simulation::CSimulatedAircraftList m_remoteAircraft; + //! \todo Add units to members? pitchDeg?, altitudeFt? struct // data is written by DBus async method callbacks { QString aircraftModelPath; diff --git a/tests/blackcore/testinterpolator.cpp b/tests/blackcore/testinterpolator.cpp index f2b8aa2fb..4dc9fc013 100644 --- a/tests/blackcore/testinterpolator.cpp +++ b/tests/blackcore/testinterpolator.cpp @@ -13,22 +13,21 @@ using namespace BlackMisc::PhysicalQuantities; namespace BlackCoreTest { -/* - * Interpolator tests - */ -void CTestInterpolator::interpolatorBasics() -{ - IInterpolator *interpolator = new CInterpolatorLinear(); + /* + * Interpolator tests + */ + void CTestInterpolator::interpolatorBasics() + { + IInterpolator *interpolator = new CInterpolatorLinear(); + QVERIFY2(!interpolator->hasEnoughAircraftSituations(), "Interpolator cannot have enough situations. They should be 0!"); - QVERIFY2(!interpolator->hasEnoughAircraftSituations(), "Interpolator cannot have enough situations. They should be 0!"); + CAircraftSituation situation; + interpolator->addAircraftSituation(situation); + QTest::qSleep(6100); + situation.setAltitude(CAltitude(500, CAltitude::MeanSeaLevel, CLengthUnit::ft())); + interpolator->addAircraftSituation(situation); - CAircraftSituation situation; - interpolator->addAircraftSituation(situation); - QTest::qSleep(6100); - situation.setHeight(CLength(500, CLengthUnit::ft())); - interpolator->addAircraftSituation(situation); - - QVERIFY2(interpolator->hasEnoughAircraftSituations(), "Interpolator should have enough situations!"); -} + QVERIFY2(interpolator->hasEnoughAircraftSituations(), "Interpolator should have enough situations!"); + } } // namespace diff --git a/tests/blackmisc/testvariantandmap.cpp b/tests/blackmisc/testvariantandmap.cpp index 692a64120..e4e0da7bc 100644 --- a/tests/blackmisc/testvariantandmap.cpp +++ b/tests/blackmisc/testvariantandmap.cpp @@ -56,7 +56,7 @@ namespace BlackMiscTest QVERIFY2(station1 == station1, "Station should be equal"); QVERIFY(station1.getController() == station2.getController()); - QVERIFY(station1.getDistanceToPlane() == station2.getDistanceToPlane()); + QVERIFY(station1.getDistanceToOwnAircraft() == station2.getDistanceToOwnAircraft()); QVERIFY2(station1 == station2, "Station should be equal"); QVERIFY2(station1 != station3, "Station should not be equal");