mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
refs #852 IInterpolator::getInterpolatedParts interpolates the onGround value.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user