diff --git a/src/blackmisc/geo/elevationplane.cpp b/src/blackmisc/geo/elevationplane.cpp index 66b02916a..701765496 100644 --- a/src/blackmisc/geo/elevationplane.cpp +++ b/src/blackmisc/geo/elevationplane.cpp @@ -11,6 +11,7 @@ #include "blackmisc/pq/length.h" #include "blackmisc/propertyindex.h" +using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; namespace BlackMisc @@ -27,6 +28,11 @@ namespace BlackMisc ); } + const CAltitude &CElevationPlane::getAltitudeIfWithinRadius(const BlackMisc::Geo::ICoordinateGeodetic &coordinate) const + { + return (isWithinRange(coordinate)) ? geodeticHeight() : CAltitude::null(); + } + bool CElevationPlane::isNull() const { return m_radius.isNull(); @@ -34,7 +40,7 @@ namespace BlackMisc bool CElevationPlane::isWithinRange(const ICoordinateGeodetic &coordinate) const { - if (m_radius.isNull()) { return false; } + if (isNull()) { return false; } const CLength d = this->calculateGreatCircleDistance(coordinate); const bool inRange = m_radius >= d; return inRange; diff --git a/src/blackmisc/geo/elevationplane.h b/src/blackmisc/geo/elevationplane.h index 2e25970ef..45752ea07 100644 --- a/src/blackmisc/geo/elevationplane.h +++ b/src/blackmisc/geo/elevationplane.h @@ -42,6 +42,9 @@ namespace BlackMisc //! Radius void setRadius(const BlackMisc::PhysicalQuantities::CLength &radius) { m_radius = radius; } + //! Altitude when within radius, else null + const Aviation::CAltitude &getAltitudeIfWithinRadius(const ICoordinateGeodetic &coordinate) const; + //! Existing value bool isNull() const; diff --git a/src/blackmisc/simulation/interpolationhints.cpp b/src/blackmisc/simulation/interpolationhints.cpp index 77c9d3a44..12d8d5f5b 100644 --- a/src/blackmisc/simulation/interpolationhints.cpp +++ b/src/blackmisc/simulation/interpolationhints.cpp @@ -26,19 +26,19 @@ namespace BlackMisc CAltitude CInterpolationHints::getGroundElevation(const Aviation::CAircraftSituation &situation) const { if (m_elevationProvider) { return m_elevationProvider(situation); } - if (m_elevation.isNull() || !m_elevation.isWithinRange(situation)) { return CAltitude::null(); } - return m_elevation.geodeticHeight(); + if (m_elevationPlane.isNull() || !m_elevationPlane.isWithinRange(situation)) { return CAltitude::null(); } + return m_elevationPlane.geodeticHeight(); } - void CInterpolationHints::resetElevation() + void CInterpolationHints::resetElevationPlane() { - m_elevation = CElevationPlane(); + m_elevationPlane = CElevationPlane(); } bool CInterpolationHints::isWithinRange(const Geo::ICoordinateGeodetic &coordinate) const { - if (m_elevation.isNull()) return false; - return m_elevation.isWithinRange(coordinate); + if (m_elevationPlane.isNull()) return false; + return m_elevationPlane.isWithinRange(coordinate); } void CInterpolationHints::setAircraftParts(const CAircraftParts &parts, bool hasParts) @@ -47,6 +47,11 @@ namespace BlackMisc m_aircraftParts = parts; } + bool CInterpolationHints::hasElevationProvider() const + { + return static_cast(m_elevationProvider); + } + CVariant CInterpolationHints::propertyByIndex(const CPropertyIndex &index) const { if (index.isMyself()) { return CVariant::from(*this); } @@ -56,7 +61,7 @@ namespace BlackMisc case IndexCenterOfGravity: return this->m_cgAboveGround.propertyByIndex(index.copyFrontRemoved()); case IndexElevationPlane: - return this->m_elevation.propertyByIndex(index.copyFrontRemoved()); + return this->m_elevationPlane.propertyByIndex(index.copyFrontRemoved()); case IndexIsVtolAircraft: return CVariant::fromValue(m_isVtol); default: @@ -74,7 +79,7 @@ namespace BlackMisc this->m_cgAboveGround.setPropertyByIndex(index.copyFrontRemoved(), variant); break; case IndexElevationPlane: - this->m_elevation.setPropertyByIndex(index.copyFrontRemoved(), variant); + this->m_elevationPlane.setPropertyByIndex(index.copyFrontRemoved(), variant); break; case IndexIsVtolAircraft: this->m_isVtol = variant.toBool(); @@ -88,17 +93,17 @@ namespace BlackMisc QString CInterpolationHints::convertToQString(bool i18n) const { static const QString s("%1 %2"); - return s.arg(m_elevation.toQString(i18n), m_cgAboveGround.toQString(i18n)); + return s.arg(m_elevationPlane.toQString(i18n), m_cgAboveGround.toQString(i18n)); } QString CInterpolationHints::debugInfo(const Geo::CElevationPlane &deltaElevation) const { static const QString s("Lat: %1 Lng: %2 Elv: %3"); - if (m_elevation.isNull() || deltaElevation.isNull()) return "null"; + if (m_elevationPlane.isNull() || deltaElevation.isNull()) return "null"; return s.arg( - (deltaElevation.latitude() - m_elevation.latitude()).valueRoundedWithUnit(CAngleUnit::deg(), 10), - (deltaElevation.longitude() - m_elevation.longitude()).valueRoundedWithUnit(CAngleUnit::deg(), 10), - (deltaElevation.geodeticHeight() - m_elevation.geodeticHeight()).valueRoundedWithUnit(CLengthUnit::ft(), 2) + (deltaElevation.latitude() - m_elevationPlane.latitude()).valueRoundedWithUnit(CAngleUnit::deg(), 10), + (deltaElevation.longitude() - m_elevationPlane.longitude()).valueRoundedWithUnit(CAngleUnit::deg(), 10), + (deltaElevation.geodeticHeight() - m_elevationPlane.geodeticHeight()).valueRoundedWithUnit(CLengthUnit::ft(), 2) ); } } // namespace diff --git a/src/blackmisc/simulation/interpolationhints.h b/src/blackmisc/simulation/interpolationhints.h index f89f4a9ba..00ea60c3b 100644 --- a/src/blackmisc/simulation/interpolationhints.h +++ b/src/blackmisc/simulation/interpolationhints.h @@ -42,17 +42,17 @@ namespace BlackMisc CInterpolationHints(bool isVtolAircraft); //! Get elevation - const BlackMisc::Geo::CElevationPlane &getElevation() const { return m_elevation;} + const BlackMisc::Geo::CElevationPlane &getElevationPlane() const { return m_elevationPlane;} + + //! Set elevation + void setElevationPlane(const BlackMisc::Geo::CElevationPlane &elevation) { m_elevationPlane = elevation; } + + //! Elevation plane set to null + void resetElevationPlane(); //! Get elevation from CInterpolationHints::getElevationProvider or CInterpolationHints::getElevation Aviation::CAltitude getGroundElevation(const BlackMisc::Aviation::CAircraftSituation &situation) const; - //! Set elevation - void setElevation(const BlackMisc::Geo::CElevationPlane &elevation) { m_elevation = elevation; } - - //! Elevation set to null - void resetElevation(); - //! Check if elevation is within radius and can be used bool isWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate) const; @@ -90,6 +90,9 @@ namespace BlackMisc //! Function object that can obtain ground elevation using ElevationProvider = std::function; + //! Has elevation provider + bool hasElevationProvider() const; + //! Function object that can obtain ground elevation //! \remark either a provider or a value set can be used const ElevationProvider &getElevationProvider() const { return m_elevationProvider; } @@ -114,14 +117,14 @@ namespace BlackMisc bool m_hasParts = false; //!< Has valid aircraft parts? bool m_logInterpolation = false; //!< log interpolation BlackMisc::Aviation::CAircraftParts m_aircraftParts; //!< Aircraft parts - BlackMisc::Geo::CElevationPlane m_elevation; //!< aircraft's elevation if available + BlackMisc::Geo::CElevationPlane m_elevationPlane; //!< aircraft's elevation if available ElevationProvider m_elevationProvider; //!< Provider of ground elevation (lazy computation) BlackMisc::PhysicalQuantities::CLength m_cgAboveGround { 0, nullptr }; //!< center of gravity above ground BLACK_METACLASS( CInterpolationHints, BLACK_METAMEMBER(isVtol), - BLACK_METAMEMBER(elevation), + BLACK_METAMEMBER(elevationPlane), BLACK_METAMEMBER(cgAboveGround), BLACK_METAMEMBER(hasParts), BLACK_METAMEMBER(aircraftParts), diff --git a/src/blackmisc/simulation/interpolatorlinear.cpp b/src/blackmisc/simulation/interpolatorlinear.cpp index 777ce4d69..5a779e610 100644 --- a/src/blackmisc/simulation/interpolatorlinear.cpp +++ b/src/blackmisc/simulation/interpolatorlinear.cpp @@ -100,7 +100,8 @@ namespace BlackMisc } // take hint into account to calculate elevation and above ground level - if (!hints.getElevation().isNull()) + // do not call for XP (lazy init) + if (!hints.hasElevationProvider()) { IInterpolator::setGroundElevationFromHint(hints, oldSituation, false); IInterpolator::setGroundElevationFromHint(hints, newSituation, false); @@ -147,11 +148,11 @@ namespace BlackMisc + oldAlt, oldAlt.getReferenceDatum())); - // update current position by hints' elevation - // for XP provided by hints.getElevationProvider at current position - // for FSX/P3D provided as hints.getElevation which is set to current position of remote aircraft in simulator - const CAltitude currentGroundElevation = hints.getGroundElevation(currentSituation); - if (!currentGroundElevation.isNull()) { currentSituation.setGroundElevation(currentGroundElevation); } + // Update current position by hints' elevation + // * for XP provided by hints.getElevationProvider at current position + // * for FSX/P3D provided as hints.getElevation which is set to current position of remote aircraft in simulator + // As XP uses lazy init we will call getGroundElevation only when needed, so default here via getElevationPlane + CAltitude currentGroundElevation(hints.getElevationPlane().getAltitudeIfWithinRadius(currentSituation)); // Interpolate between altitude and ground elevation, with proportions weighted according to interpolated onGround flag if (hints.hasAircraftParts()) @@ -160,6 +161,7 @@ namespace BlackMisc log.groundFactor = groundFactor; if (groundFactor > 0.0) { + currentGroundElevation = hints.getGroundElevation(currentSituation); // calls provider on XP if (!currentGroundElevation.isNull()) { Q_ASSERT_X(currentGroundElevation.getReferenceDatum() == CAltitude::MeanSeaLevel, Q_FUNC_INFO, "Need MSL value"); @@ -168,12 +170,14 @@ namespace BlackMisc oldAlt.getReferenceDatum())); } } + currentSituation.setGroundElevation(currentGroundElevation); IInterpolator::setGroundFlagFromInterpolator(hints, groundFactor, currentSituation); } else { // guess ground flag constexpr double NoGroundFactor = -1; + currentSituation.setGroundElevation(currentGroundElevation); IInterpolator::setGroundFlagFromInterpolator(hints, NoGroundFactor, currentSituation); } diff --git a/src/plugins/simulator/fsx/simulatorfsx.cpp b/src/plugins/simulator/fsx/simulatorfsx.cpp index 1ffd3ba3e..96a00b2af 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.cpp +++ b/src/plugins/simulator/fsx/simulatorfsx.cpp @@ -507,7 +507,7 @@ namespace BlackSimPlugin // const QString debug(hints.debugInfo(elevation)); CInterpolationHints &hints = m_hints[simObject.getCallsign()]; - hints.setElevation(elevation); // update elevation + hints.setElevationPlane(elevation); // update elevation hints.setCGAboveGround({ remoteAircraftData.cgToGround, CLengthUnit::ft() }); // normally never changing, but if user changes ModelMatching // set it in the remote aircraft provider