refs #852 IInterpolator::getInterpolatedParts interpolates the onGround value.

This commit is contained in:
Mathew Sutcliffe
2017-01-09 18:43:31 +00:00
parent 3f5139d717
commit 8a924d5b1c
2 changed files with 43 additions and 3 deletions

View File

@@ -10,6 +10,7 @@
#include "interpolator.h" #include "interpolator.h"
#include "blackmisc/aviation/callsign.h" #include "blackmisc/aviation/callsign.h"
#include "blackmisc/simulation/interpolationhints.h" #include "blackmisc/simulation/interpolationhints.h"
#include <QDateTime>
using namespace BlackMisc::Aviation; using namespace BlackMisc::Aviation;
@@ -42,11 +43,38 @@ namespace BlackMisc
CAircraftParts IInterpolator::getInterpolatedParts(const CAircraftPartsList &parts, qint64 currentTimeMsSinceEpoch, IInterpolator::PartsStatus &partsStatus) const CAircraftParts IInterpolator::getInterpolatedParts(const CAircraftPartsList &parts, qint64 currentTimeMsSinceEpoch, IInterpolator::PartsStatus &partsStatus) const
{ {
partsStatus.reset(); partsStatus.reset();
if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
// find the first parts not in the correct order, keep only the parts before that one
const auto end = std::is_sorted_until(parts.begin(), parts.end(), [](auto && a, auto && b) { return b.getAdjustedMSecsSinceEpoch() < a.getAdjustedMSecsSinceEpoch(); });
const auto validParts = makeRange(parts.begin(), end);
// stop if we don't have any parts
if (validParts.isEmpty()) { return {}; }
partsStatus.setSupportsParts(true); partsStatus.setSupportsParts(true);
if (parts.isEmpty()) { return {}; } // find the first parts earlier than the current time
if (currentTimeMsSinceEpoch < 0) { return parts.front(); } const auto pivot = std::partition_point(validParts.begin(), validParts.end(), [ = ](auto && p) { return p.getAdjustedMSecsSinceEpoch() > currentTimeMsSinceEpoch; });
return parts.findBefore(currentTimeMsSinceEpoch).front(); const auto partsNewer = makeRange(validParts.begin(), pivot).reverse();
const auto partsOlder = makeRange(pivot, validParts.end());
if (partsOlder.isEmpty()) { return *(partsNewer.end() - 1); }
CAircraftParts currentParts = partsOlder.front();
if (currentParts.isOnGround()) { return currentParts; }
// here we know aircraft is not on ground, and we check if it was recently on ground or if it will be on ground soon
const auto latestTakeoff = std::adjacent_find(partsOlder.begin(), partsOlder.end(), [](auto &&, auto && p) { return p.isOnGround(); });
const auto soonestLanding = std::find_if(partsNewer.begin(), partsNewer.end(), [](auto && p) { return p.isOnGround(); });
const double secondsSinceTakeoff = latestTakeoff == partsOlder.end() ? 5.0 : (currentTimeMsSinceEpoch - latestTakeoff->getAdjustedMSecsSinceEpoch()) / 1000.0;
const double secondsUntilLanding = soonestLanding == partsNewer.end() ? 5.0 : (soonestLanding->getAdjustedMSecsSinceEpoch() - currentTimeMsSinceEpoch) / 1000.0;
const double secondsAirborne = std::min(secondsSinceTakeoff, secondsUntilLanding);
Q_ASSERT(secondsAirborne >= 0.0);
const double airborneFactor = std::min(secondsAirborne / 5.0, 1.0);
currentParts.setOnGroundInterpolated(1.0 - smootherStep(airborneFactor));
return currentParts;
} }
CAircraftParts IInterpolator::getInterpolatedParts(const CCallsign &callsign, qint64 currentTimeMsSinceEpoch, IInterpolator::PartsStatus &partsStatus) const CAircraftParts IInterpolator::getInterpolatedParts(const CCallsign &callsign, qint64 currentTimeMsSinceEpoch, IInterpolator::PartsStatus &partsStatus) const

View File

@@ -119,6 +119,18 @@ namespace BlackMisc
//! \threadsafe //! \threadsafe
void setInterpolatorSetup(const CInterpolationAndRenderingSetup &setup); void setInterpolatorSetup(const CInterpolationAndRenderingSetup &setup);
/*!
* Takes input between 0 and 1 and returns output between 0 and 1 smoothed with an S-shaped curve.
*
* Useful for making interpolation seem smoother, efficiently as it just uses simple arithmetic.
* \see https://en.wikipedia.org/wiki/Smoothstep
* \see http://sol.gfxile.net/interpolation/
*/
static double smootherStep(double x)
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
protected: protected:
//! Constructor //! Constructor
IInterpolator(BlackMisc::Simulation::IRemoteAircraftProvider *provider, const QString &objectName, QObject *parent); IInterpolator(BlackMisc::Simulation::IRemoteAircraftProvider *provider, const QString &objectName, QObject *parent);