diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 57a546871..f192903f0 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -1423,10 +1423,11 @@ namespace BlackCore bool fromNonMoving = false; bool triedExtrapolation = false; bool couldNotExtrapolate = false; + CElevationPlane averagePlane = this->averageElevationOfOnGroundAircraft(situation, CElevationPlane::majorAirportRadius(), 2, 3); if (averagePlane.isNull()) { - averagePlane = this->averageElevationOfNonMovingAircraft(situation, CElevationPlane::majorAirportRadius(), 2); + averagePlane = this->averageElevationOfNonMovingAircraft(situation, CElevationPlane::majorAirportRadius(), 2, 3); fromNonMoving = true; } diff --git a/src/blackcore/context/contextnetworkimpl.cpp b/src/blackcore/context/contextnetworkimpl.cpp index 875dd7760..649518b8c 100644 --- a/src/blackcore/context/contextnetworkimpl.cpp +++ b/src/blackcore/context/contextnetworkimpl.cpp @@ -1181,9 +1181,9 @@ namespace BlackCore return m_airspace->getLatestAirspaceAircraftSnapshot(); } - CElevationPlane CContextNetwork::averageElevationOfNonMovingAircraft(const CAircraftSituation &reference, const CLength &range, int minValues) const + CElevationPlane CContextNetwork::averageElevationOfNonMovingAircraft(const CAircraftSituation &reference, const CLength &range, int minValues, int sufficientValues) const { - return m_airspace->averageElevationOfNonMovingAircraft(reference, range, minValues); + return m_airspace->averageElevationOfNonMovingAircraft(reference, range, minValues, sufficientValues); } void CContextNetwork::setClients(const CClientList &clients) diff --git a/src/blackcore/context/contextnetworkimpl.h b/src/blackcore/context/contextnetworkimpl.h index 389772e84..789aef454 100644 --- a/src/blackcore/context/contextnetworkimpl.h +++ b/src/blackcore/context/contextnetworkimpl.h @@ -119,7 +119,7 @@ namespace BlackCore virtual void rememberCGFromDB(const BlackMisc::PhysicalQuantities::CLength &cgFromDB, const BlackMisc::Aviation::CCallsign &callsign) override; virtual void rememberCGFromDB(const BlackMisc::PhysicalQuantities::CLength &cgFromDB, const QString &modelString) override; virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override; - virtual BlackMisc::Geo::CElevationPlane averageElevationOfNonMovingAircraft(const BlackMisc::Aviation::CAircraftSituation &reference, const BlackMisc::PhysicalQuantities::CLength &range, int minValues = 1) const override; + virtual BlackMisc::Geo::CElevationPlane averageElevationOfNonMovingAircraft(const BlackMisc::Aviation::CAircraftSituation &reference, const BlackMisc::PhysicalQuantities::CLength &range, int minValues = 1, int sufficientValues = 2) const override; virtual QList connectRemoteAircraftProviderSignals( QObject *receiver, std::function addedSituationSlot, diff --git a/src/blackmisc/aviation/aircraftsituationlist.cpp b/src/blackmisc/aviation/aircraftsituationlist.cpp index 482abc3c6..b8f87ede2 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.cpp +++ b/src/blackmisc/aviation/aircraftsituationlist.cpp @@ -611,25 +611,25 @@ namespace BlackMisc return c; } - CElevationPlane CAircraftSituationList::averageElevationOfTaxiingOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues) const + CElevationPlane CAircraftSituationList::averageElevationOfTaxiingOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues, int sufficientValues) const { if (this->size() < minValues) { return CElevationPlane::null(); } // no change to succeed + const CAircraftSituationList sorted = this->findWithGeodeticMSLHeight().findWithinRange(reference, range).sortedByEuclideanDistanceSquared(reference); + if (sorted.size() < minValues) { return CElevationPlane::null(); } QList valuesInFt; - int count = 0; for (const CAircraftSituation &situation : *this) { if (situation.getGroundElevationInfo() != CAircraftSituation::FromProvider) { continue; } const bool canUse = !situation.isMoving() || (situation.isOnGroundFromNetwork() || situation.isOnGroundFromParts()); if (!canUse) { continue; } - if (!situation.isWithinRange(reference, range)) { continue; } + const double elvFt = situation.getGroundElevationPlane().getAltitude().value(CLengthUnit::ft()); valuesInFt.push_back(elvFt); - count++; - if (count > 5 && valuesInFt.size() > 3 * minValues) { break; } + if (valuesInFt.size() >= sufficientValues) { break; } } - if (count < minValues) { return CElevationPlane::null(); } + if (valuesInFt.size() < minValues) { return CElevationPlane::null(); } static const double MaxDevFt = CAircraftSituationChange::allowedAltitudeDeviation().value(CLengthUnit::ft()); const QPair elvStdDevMean = CMathUtils::standardDeviationAndMean(valuesInFt); diff --git a/src/blackmisc/aviation/aircraftsituationlist.h b/src/blackmisc/aviation/aircraftsituationlist.h index 09fb5fcd6..ad7df9248 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.h +++ b/src/blackmisc/aviation/aircraftsituationlist.h @@ -208,7 +208,7 @@ namespace BlackMisc int transferElevationForward(const PhysicalQuantities::CLength &radius = Geo::CElevationPlane::singlePointRadius()); //! Average elevation for "nearby" aircraft "not/slowly moving" and having an elevation - Geo::CElevationPlane averageElevationOfTaxiingOnGroundAircraft(const CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1) const; + Geo::CElevationPlane averageElevationOfTaxiingOnGroundAircraft(const CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1, int sufficientValues = 2) const; }; //! Situation per callsign diff --git a/src/blackmisc/geo/coordinategeodeticlist.cpp b/src/blackmisc/geo/coordinategeodeticlist.cpp index 00c903e38..8d61e8b62 100644 --- a/src/blackmisc/geo/coordinategeodeticlist.cpp +++ b/src/blackmisc/geo/coordinategeodeticlist.cpp @@ -27,23 +27,23 @@ namespace BlackMisc CSequence(other) { } - CElevationPlane CCoordinateGeodeticList::averageGeodeticHeight(const CCoordinateGeodetic &reference, const CLength &range, const CLength &maxDeviation, int minValues) const + CElevationPlane CCoordinateGeodeticList::averageGeodeticHeight(const CCoordinateGeodetic &reference, const CLength &range, const CLength &maxDeviation, int minValues, int sufficentValues) const { if (this->size() < minValues) { return CElevationPlane::null(); } // no change to succeed QList valuesInFt; - int count = 0; - for (const CCoordinateGeodetic &coordinate : *this) + const CCoordinateGeodeticList sorted = this->findWithGeodeticMSLHeight().findWithinRange(reference, range).sortedByEuclideanDistanceSquared(reference); + if (sorted.size() < minValues) { return CElevationPlane::null(); } + + // we know all values have MSL and are within range + for (const CCoordinateGeodetic &coordinate : sorted) { - if (!coordinate.hasMSLGeodeticHeight()) { continue; } - if (!coordinate.isWithinRange(reference, range)) { continue; } const double elvFt = coordinate.geodeticHeight().value(CLengthUnit::ft()); valuesInFt.push_back(elvFt); - count++; - if (count > 5 && valuesInFt.size() > 3 * minValues) { break; } + if (valuesInFt.size() >= sufficentValues) { break; } } - if (count < minValues) { return CElevationPlane::null(); } + if (valuesInFt.size() < minValues) { return CElevationPlane::null(); } const double MaxDevFt = maxDeviation.value(CLengthUnit::ft()); const QPair elvStdDevMean = CMathUtils::standardDeviationAndMean(valuesInFt); diff --git a/src/blackmisc/geo/coordinategeodeticlist.h b/src/blackmisc/geo/coordinategeodeticlist.h index af320d296..c4358a4e3 100644 --- a/src/blackmisc/geo/coordinategeodeticlist.h +++ b/src/blackmisc/geo/coordinategeodeticlist.h @@ -47,7 +47,7 @@ namespace BlackMisc CCoordinateGeodeticList(const CSequence &other); //! Average height within range and having an height - CElevationPlane averageGeodeticHeight(const CCoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, const PhysicalQuantities::CLength &maxDeviation = PhysicalQuantities::CLength(1.0, PhysicalQuantities::CLengthUnit::m()), int minValues = 3) const; + CElevationPlane averageGeodeticHeight(const CCoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, const PhysicalQuantities::CLength &maxDeviation = PhysicalQuantities::CLength(1.0, PhysicalQuantities::CLengthUnit::m()), int minValues = 3, int sufficentValues = 5) const; }; } //namespace } // namespace diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index b27a6c6be..bd5120ca3 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -767,10 +767,10 @@ namespace BlackMisc return m_partsLastModified.value(callsign, -1); } - CElevationPlane CRemoteAircraftProvider::averageElevationOfNonMovingAircraft(const CAircraftSituation &reference, const CLength &range, int minValues) const + CElevationPlane CRemoteAircraftProvider::averageElevationOfNonMovingAircraft(const CAircraftSituation &reference, const CLength &range, int minValues, int sufficientValues) const { const CAircraftSituationList situations = this->latestOnGroundProviderElevations(); - return situations.averageElevationOfTaxiingOnGroundAircraft(reference, range, minValues); + return situations.averageElevationOfTaxiingOnGroundAircraft(reference, range, minValues, sufficientValues); } bool CRemoteAircraftProvider::testAddAltitudeOffset(const CCallsign &callsign, const CLength &offset) diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index 7da923395..71fdc7a52 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -251,7 +251,7 @@ namespace BlackMisc //! Average elevation of aircraft in given range, which are NOT moving //! \remark can be used to anticipate field elevation //! \threadsafe - virtual Geo::CElevationPlane averageElevationOfNonMovingAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1) const = 0; + virtual Geo::CElevationPlane averageElevationOfNonMovingAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1, int sufficientValues = 2) const = 0; //! Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly. //! In order to disconnect a list of connections is provided, which have to be disconnected manually. @@ -344,7 +344,7 @@ namespace BlackMisc virtual int aircraftPartsAdded() const override; virtual qint64 situationsLastModified(const Aviation::CCallsign &callsign) const override; virtual qint64 partsLastModified(const Aviation::CCallsign &callsign) const override; - virtual Geo::CElevationPlane averageElevationOfNonMovingAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1) const override; + virtual Geo::CElevationPlane averageElevationOfNonMovingAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues = 1, int sufficientValues = 2) const override; virtual QList connectRemoteAircraftProviderSignals( QObject *receiver, std::function addedSituationSlot, diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index e2efb353c..24ebec0e1 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -167,10 +167,10 @@ namespace BlackMisc return m_elvCoordinatesGnd; } - CElevationPlane ISimulationEnvironmentProvider::averageElevationOfOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues) const + CElevationPlane ISimulationEnvironmentProvider::averageElevationOfOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues, int sufficientValues) const { const CCoordinateGeodeticList coordinates = this->getElevationCoordinatesOnGround(); - return coordinates.averageGeodeticHeight(reference, range, CAircraftSituationChange::allowedAltitudeDeviation(), minValues); + return coordinates.averageGeodeticHeight(reference, range, CAircraftSituationChange::allowedAltitudeDeviation(), minValues, sufficientValues); } CAltitude ISimulationEnvironmentProvider::highestElevation() const @@ -592,10 +592,10 @@ namespace BlackMisc return this->provider()->findClosestElevationWithinRangeOrRequest(reference, range, callsign); } - CElevationPlane CSimulationEnvironmentAware::averageElevationOfOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues) const + CElevationPlane CSimulationEnvironmentAware::averageElevationOfOnGroundAircraft(const CAircraftSituation &reference, const CLength &range, int minValues, int sufficientValues) const { if (!this->hasProvider()) { return CElevationPlane::null(); } - return this->provider()->averageElevationOfOnGroundAircraft(reference, range, minValues); + return this->provider()->averageElevationOfOnGroundAircraft(reference, range, minValues, sufficientValues); } CAltitude CSimulationEnvironmentAware::highestElevation() const diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.h b/src/blackmisc/simulation/simulationenvironmentprovider.h index 0906cdb03..71d4dd559 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.h +++ b/src/blackmisc/simulation/simulationenvironmentprovider.h @@ -44,7 +44,7 @@ namespace BlackMisc //! Average elevation of "on ground" cached values //! \threadsafe - Geo::CElevationPlane averageElevationOfOnGroundAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues) const; + Geo::CElevationPlane averageElevationOfOnGroundAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues, int sufficientValues) const; //! Highest elevation //! \threadsafe @@ -298,7 +298,7 @@ namespace BlackMisc Geo::CElevationPlane findClosestElevationWithinRangeOrRequest(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, const Aviation::CCallsign &callsign); //! \copydoc ISimulationEnvironmentProvider::averageElevationOfOnGroundAircraft - Geo::CElevationPlane averageElevationOfOnGroundAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues) const; + Geo::CElevationPlane averageElevationOfOnGroundAircraft(const Aviation::CAircraftSituation &reference, const PhysicalQuantities::CLength &range, int minValues, int sufficientValues) const; //! \copydoc ISimulationEnvironmentProvider::highestElevation Aviation::CAltitude highestElevation() const;