From 5b4f672c754d7b19bafdf25ba52110244265d755 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Mon, 9 Jan 2017 18:51:20 +0000 Subject: [PATCH] refs #852 Use X-Plane terrain probe to provide ground elevation to the interpolator. --- src/xbus/terrainprobe.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/xbus/terrainprobe.h | 39 +++++++++++++++++++++++++++++++++++++++ src/xbus/traffic.cpp | 20 ++++++++++++++++++-- src/xbus/traffic.h | 12 +++++++++++- 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/xbus/terrainprobe.cpp create mode 100644 src/xbus/terrainprobe.h diff --git a/src/xbus/terrainprobe.cpp b/src/xbus/terrainprobe.cpp new file mode 100644 index 000000000..9739718cc --- /dev/null +++ b/src/xbus/terrainprobe.cpp @@ -0,0 +1,36 @@ +/* Copyright (C) 2017 + * 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 "terrainprobe.h" +#include +#include + +namespace XBus +{ + CTerrainProbe::CTerrainProbe() : m_ref(XPLMCreateProbe(xplm_ProbeY)) {} + + CTerrainProbe::~CTerrainProbe() { XPLMDestroyProbe(m_ref); } + + double CTerrainProbe::getElevation(double degreesLatitude, double degreesLongitude, double metersAltitude) const + { + double x, y, z; + XPLMWorldToLocal(degreesLatitude, degreesLongitude, metersAltitude, &x, &y, &z); + + XPLMProbeInfo_t probe; + probe.structSize = sizeof(probe); + auto result = XPLMProbeTerrainXYZ(m_ref, static_cast(x), static_cast(y), static_cast(z), &probe); + if (result != xplm_ProbeHitTerrain) + { + return std::numeric_limits::quiet_NaN(); + } + + XPLMLocalToWorld(probe.locationX, probe.locationY, probe.locationZ, °reesLatitude, °reesLongitude, &metersAltitude); + return metersAltitude; + } +} diff --git a/src/xbus/terrainprobe.h b/src/xbus/terrainprobe.h new file mode 100644 index 000000000..50a02463e --- /dev/null +++ b/src/xbus/terrainprobe.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2017 + * 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. + */ + +#ifndef BLACKSIM_XBUS_ELEVATIONPROVIDER_H +#define BLACKSIM_XBUS_ELEVATIONPROVIDER_H + +#include + +namespace XBus +{ + /*! + * Class based interface to X-Plane SDK terrain probe. + */ + class CTerrainProbe + { + public: + //! Constructor. + CTerrainProbe(); + + //! Destructor; + ~CTerrainProbe(); + + //! Get the elevation in meters at the given point in OpenGL space. + //! \note Due to the Earth's curvature, the OpenGL vertical axis may not be exactly perpendicular to the surface of the geoid. + //! \return NaN if no ground was detected. + double getElevation(double degreesLatitude, double degreesLongitude, double metersAltitude) const; + + private: + XPLMProbeRef m_ref = nullptr; + }; +} + +#endif diff --git a/src/xbus/traffic.cpp b/src/xbus/traffic.cpp index 8dc4d8d14..de7926075 100644 --- a/src/xbus/traffic.cpp +++ b/src/xbus/traffic.cpp @@ -42,6 +42,23 @@ namespace XBus surfaces.lights.timeOffset = static_cast(qrand() % 0xffff); } + BlackMisc::Simulation::CInterpolationHints CTraffic::Plane::hints(BlackMisc::Simulation::IInterpolator *interpolator) const + { + BlackMisc::Simulation::CInterpolationHints hints; + BlackMisc::Simulation::IInterpolator::PartsStatus status; + hints.setAircraftParts(interpolator->getInterpolatedParts(parts, -1, status)); + hints.setElevationProvider([this](const auto &situation) + { + using namespace BlackMisc::PhysicalQuantities; + const auto meters = terrainProbe.getElevation(situation.latitude().value(CAngleUnit::deg()), + situation.longitude().value(CAngleUnit::deg()), + situation.getAltitude().value(CLengthUnit::m())); + if (std::isnan(meters)) { return CLength(0, nullptr); } + return CLength(meters, CLengthUnit::m()); + }); + return hints; + } + CTraffic::CTraffic(QObject *parent) : QObject(parent), m_interpolator(new BlackMisc::Simulation::CInterpolatorLinear(new BlackMisc::Simulation::CRemoteAircraftProviderDummy(this), this)) @@ -316,8 +333,7 @@ namespace XBus case xpmpDataType_Position: { BlackMisc::Simulation::IInterpolator::InterpolationStatus status; - const BlackMisc::Simulation::CInterpolationHints hints; - const auto situation = m_interpolator->getInterpolatedSituation(plane->situations, -1, hints, status); + const auto situation = m_interpolator->getInterpolatedSituation(plane->situations, -1, plane->hints(m_interpolator), status); if (! status.didInterpolationSucceed()) { return xpmpData_Unavailable; } if (! status.hasChangedPosition()) { return xpmpData_Unchanged; } diff --git a/src/xbus/traffic.h b/src/xbus/traffic.h index 3e921f463..f8846e0d3 100644 --- a/src/xbus/traffic.h +++ b/src/xbus/traffic.h @@ -13,6 +13,7 @@ //! \file #include "datarefs.h" +#include "terrainprobe.h" #include "blackmisc/aviation/aircraftsituationlist.h" #include "blackmisc/aviation/aircraftpartslist.h" #include @@ -26,7 +27,14 @@ #define XBUS_TRAFFIC_OBJECTPATH "/xbus/traffic" //! \endcond -namespace BlackMisc { namespace Simulation { class IInterpolator; } } +namespace BlackMisc +{ + namespace Simulation + { + class IInterpolator; + class CInterpolationHints; + } +} namespace XBus { /*! @@ -131,6 +139,8 @@ namespace XBus char label[32] {}; BlackMisc::Aviation::CAircraftSituationList situations; BlackMisc::Aviation::CAircraftPartsList parts; + CTerrainProbe terrainProbe; + BlackMisc::Simulation::CInterpolationHints hints(BlackMisc::Simulation::IInterpolator *) const; XPMPPlaneSurfaces_t surfaces; XPMPPlaneRadar_t xpdr; Plane(void *id_, QString callsign_, QString aircraftIcao_, QString airlineIcao_, QString livery_);