diff --git a/src/blackcore/simulatorcommon.h b/src/blackcore/simulatorcommon.h index ad1c90fb9..62e7c6c08 100644 --- a/src/blackcore/simulatorcommon.h +++ b/src/blackcore/simulatorcommon.h @@ -49,7 +49,6 @@ namespace BlackMisc } namespace Simulation { - class IInterpolator; class CAirspaceAircraftSnapshot; class CSimulatedAircraft; } diff --git a/src/blackmisc/simulation/interpolator.cpp b/src/blackmisc/simulation/interpolator.cpp index 043166bcd..7102ba058 100644 --- a/src/blackmisc/simulation/interpolator.cpp +++ b/src/blackmisc/simulation/interpolator.cpp @@ -10,6 +10,7 @@ #include "interpolator.h" #include "blackconfig/buildconfig.h" #include "blackmisc/simulation/interpolationhints.h" +#include "blackmisc/simulation/interpolatorlinear.h" #include "blackmisc/aviation/callsign.h" #include "blackmisc/pq/length.h" #include "blackmisc/logmessage.h" @@ -27,24 +28,27 @@ namespace BlackMisc { namespace Simulation { - IInterpolator::IInterpolator(const QString &objectName, QObject *parent) : + template + CInterpolator::CInterpolator(const QString &objectName, QObject *parent) : QObject(parent) { this->setObjectName(objectName); } - BlackMisc::Aviation::CAircraftSituation IInterpolator::getInterpolatedSituation( + template + BlackMisc::Aviation::CAircraftSituation CInterpolator::getInterpolatedSituation( qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints, CInterpolationStatus &status) const { status.reset(); - auto currentSituation = this->getInterpolatedSituation(callsign, this->m_aircraftSituations, currentTimeSinceEpoc, setup, hints, status); + auto currentSituation = derived()->getInterpolatedSituation(callsign, this->m_aircraftSituations, currentTimeSinceEpoc, setup, hints, status); currentSituation.setCallsign(callsign); // make sure callsign is correct return currentSituation; } - CAircraftParts IInterpolator::getInterpolatedParts(const CCallsign &callsign, const CAircraftPartsList &parts, qint64 currentTimeMsSinceEpoch, + template + CAircraftParts CInterpolator::getInterpolatedParts(const CCallsign &callsign, const CAircraftPartsList &parts, qint64 currentTimeMsSinceEpoch, const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log) const { Q_UNUSED(setup); @@ -102,31 +106,35 @@ namespace BlackMisc log.callsign = callsign; log.timestamp = currentTimeMsSinceEpoch; log.parts = currentParts; - IInterpolator::logParts(log); + CInterpolator::logParts(log); } return currentParts; } - CAircraftParts IInterpolator::getInterpolatedParts(const CCallsign &callsign, qint64 currentTimeMsSinceEpoch, + template + CAircraftParts CInterpolator::getInterpolatedParts(const CCallsign &callsign, qint64 currentTimeMsSinceEpoch, const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log) const { partsStatus.reset(); return this->getInterpolatedParts(callsign, this->m_aircraftParts, currentTimeMsSinceEpoch, setup, partsStatus, log); } - void IInterpolator::addAircraftSituation(const CAircraftSituation &situation) + template + void CInterpolator::addAircraftSituation(const CAircraftSituation &situation) { m_aircraftSituations.push_frontMaxElements(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign); } - void IInterpolator::addAircraftParts(const CAircraftParts &parts) + template + void CInterpolator::addAircraftParts(const CAircraftParts &parts) { m_aircraftParts.push_front(parts); IRemoteAircraftProvider::removeOutdatedParts(m_aircraftParts); } - CWorker *IInterpolator::writeLogInBackground() + template + CWorker *CInterpolator::writeLogInBackground() { QList interpolation; QList parts; @@ -138,7 +146,7 @@ namespace BlackMisc CWorker *worker = CWorker::fromTask(this, "WriteInterpolationLog", [interpolation, parts]() { - const CStatusMessageList msg = IInterpolator::writeLogFile(interpolation, parts); + const CStatusMessageList msg = CInterpolator::writeLogFile(interpolation, parts); CLogMessage::preformatted(msg); }); return worker; @@ -164,57 +172,62 @@ namespace BlackMisc return files; } - CStatusMessageList IInterpolator::writeLogFile(const QList &interpolation, const QList &parts) + template + CStatusMessageList CInterpolator::writeLogFile(const QList &interpolation, const QList &parts) { - if (parts.isEmpty() && interpolation.isEmpty()) { return CStatusMessage(static_cast(nullptr)).warning("No data for log"); } + if (parts.isEmpty() && interpolation.isEmpty()) { return CStatusMessage(static_cast(nullptr)).warning("No data for log"); } static const QString html = QLatin1String("Entries: %1\n\n%2"); const QString htmlTemplate = CFileUtils::readFileToString(CBuildConfig::getHtmlTemplateFileName()); CStatusMessageList msgs; const QString ts = QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmss"); - const QString htmlInterpolation = IInterpolator::getHtmlInterpolationLog(interpolation); + const QString htmlInterpolation = CInterpolator::getHtmlInterpolationLog(interpolation); if (!htmlInterpolation.isEmpty()) { const QString fn = CFileUtils::appendFilePaths(CDirectoryUtils::getLogDirectory(), QString("%1 interpolation.html").arg(ts)); const bool s = CFileUtils::writeStringToFile(htmlTemplate.arg(html.arg(interpolation.size()).arg(htmlInterpolation)), fn); - msgs.push_back(IInterpolator::logStatusFileWriting(s, fn)); + msgs.push_back(CInterpolator::logStatusFileWriting(s, fn)); } - const QString htmlParts = IInterpolator::getHtmlPartsLog(parts); + const QString htmlParts = CInterpolator::getHtmlPartsLog(parts); if (!htmlParts.isEmpty()) { const QString fn = CFileUtils::appendFilePaths(CDirectoryUtils::getLogDirectory(), QString("%1 parts.html").arg(ts)); const bool s = CFileUtils::writeStringToFile(htmlTemplate.arg(html.arg(parts.size()).arg(htmlParts)), fn); - msgs.push_back(IInterpolator::logStatusFileWriting(s, fn)); + msgs.push_back(CInterpolator::logStatusFileWriting(s, fn)); } return msgs; } - CStatusMessage IInterpolator::logStatusFileWriting(bool success, const QString &fileName) + template + CStatusMessage CInterpolator::logStatusFileWriting(bool success, const QString &fileName) { if (success) { - return CStatusMessage(static_cast(nullptr)).info("Written log file '%1'") << fileName; + return CStatusMessage(static_cast(nullptr)).info("Written log file '%1'") << fileName; } else { - return CStatusMessage(static_cast(nullptr)).error("Failed to write log file '%1'") << fileName; + return CStatusMessage(static_cast(nullptr)).error("Failed to write log file '%1'") << fileName; } } - void IInterpolator::logInterpolation(const IInterpolator::InterpolationLog &log) const + template + void CInterpolator::logInterpolation(const typename CInterpolator::InterpolationLog &log) const { QWriteLocker l(&m_lockLogs); m_interpolationLogs.append(log); } - void IInterpolator::logParts(const IInterpolator::PartsLog &parts) const + template + void CInterpolator::logParts(const typename CInterpolator::PartsLog &parts) const { QWriteLocker l(&m_lockLogs); m_partsLogs.append(parts); } - QString IInterpolator::getHtmlInterpolationLog(const QList &logs) + template + QString CInterpolator::getHtmlInterpolationLog(const QList &logs) { if (logs.isEmpty()) { return {}; } const QString tableHeader = @@ -294,7 +307,8 @@ namespace BlackMisc return QLatin1String("\n") % tableHeader % tableRows % QLatin1String("
\n"); } - QString IInterpolator::getHtmlPartsLog(const QList &logs) + template + QString CInterpolator::getHtmlPartsLog(const QList &logs) { if (logs.isEmpty()) { return {}; } const QString tableHeader = @@ -321,14 +335,16 @@ namespace BlackMisc return QLatin1String("\n") % tableHeader % tableRows % QLatin1String("
\n"); } - void IInterpolator::clearLog() + template + void CInterpolator::clearLog() { QWriteLocker l(&m_lockLogs); this->m_partsLogs.clear(); this->m_interpolationLogs.clear(); } - void IInterpolator::setGroundElevationFromHint(const CInterpolationHints &hints, CAircraftSituation &situation, bool override) + template + void CInterpolator::setGroundElevationFromHint(const CInterpolationHints &hints, CAircraftSituation &situation, bool override) { if (!override && situation.hasGroundElevation()) { return; } const CAltitude elevation = hints.getGroundElevation(situation); @@ -336,7 +352,8 @@ namespace BlackMisc situation.setGroundElevation(elevation); } - void IInterpolator::setGroundFlagFromInterpolator(const CInterpolationHints &hints, double groundFactor, CAircraftSituation &situation) + template + void CInterpolator::setGroundFlagFromInterpolator(const CInterpolationHints &hints, double groundFactor, CAircraftSituation &situation) { // by interpolation if (groundFactor >= 1.0) @@ -386,13 +403,15 @@ namespace BlackMisc situation.setOnGround(CAircraftSituation::OnGround, CAircraftSituation::OnGroundByGuessing); } - QString IInterpolator::msSinceEpochToTime(qint64 ms) + template + QString CInterpolator::msSinceEpochToTime(qint64 ms) { static const QString dateFormat("hh:mm:ss.zzz"); return QDateTime::fromMSecsSinceEpoch(ms).toString(dateFormat); } - QString IInterpolator::msSinceEpochToTime(qint64 t1, qint64 t2, qint64 t3) + template + QString CInterpolator::msSinceEpochToTime(qint64 t1, qint64 t2, qint64 t3) { if (t3 < 0) return QString("%1 %2").arg(msSinceEpochToTime(t1), msSinceEpochToTime(t2)); return QString("%1 %2 %3").arg(msSinceEpochToTime(t1), msSinceEpochToTime(t2), msSinceEpochToTime(t3)); @@ -418,5 +437,11 @@ namespace BlackMisc { m_supportsParts = false; } + + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + //! \cond PRIVATE + template class BLACKMISC_EXPORT_DEFINE_TEMPLATE CInterpolator; + //! \endcond } // namespace } // namespace diff --git a/src/blackmisc/simulation/interpolator.h b/src/blackmisc/simulation/interpolator.h index ae87b7422..36781fda9 100644 --- a/src/blackmisc/simulation/interpolator.h +++ b/src/blackmisc/simulation/interpolator.h @@ -13,7 +13,6 @@ #define BLACKMISC_SIMULATION_INTERPOLATOR_H #include "interpolationrenderingsetup.h" -#include "blackmisc/blackmiscexport.h" #include "blackmisc/aviation/aircraftpartslist.h" #include "blackmisc/aviation/aircraftsituation.h" #include "blackmisc/aviation/aircraftpartslist.h" @@ -30,37 +29,41 @@ namespace BlackMisc namespace Simulation { class CInterpolationHints; + class CInterpolatorLinear; struct CInterpolationStatus; struct CPartsStatus; //! Interpolator, calculation inbetween positions - class BLACKMISC_EXPORT IInterpolator : public QObject + template + class CInterpolator : public QObject { - Q_OBJECT - public: //! Log category static QString getLogCategory() { return "swift.interpolator"; } //! Current interpolated situation - virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( + BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( const BlackMisc::Aviation::CCallsign &callsign, qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints, CInterpolationStatus &status) const; //! Current interpolated situation, to be implemented by subclass - virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( + BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituationList &situations, qint64 currentTimeSinceEpoc, - const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints, CInterpolationStatus &status) const = 0; + const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints, CInterpolationStatus &status) const + { + qFatal("Not implemented"); + return {}; + } //! Parts before given offset time (aka pending parts) - virtual BlackMisc::Aviation::CAircraftParts getInterpolatedParts( + BlackMisc::Aviation::CAircraftParts getInterpolatedParts( const Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftPartsList &parts, qint64 cutoffTime, const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log = false) const; //! Parts before given offset time (aka pending parts) - virtual BlackMisc::Aviation::CAircraftParts getInterpolatedParts( + BlackMisc::Aviation::CAircraftParts getInterpolatedParts( const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTime, const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log = false) const; @@ -120,7 +123,7 @@ namespace BlackMisc }; //! Constructor - IInterpolator(const QString &objectName, QObject *parent); + CInterpolator(const QString &objectName, QObject *parent); //! Log current interpolation cycle, only stores in memory, for performance reasons //! \remark const to allow const interpolator functions @@ -159,6 +162,9 @@ namespace BlackMisc //! Create readable time static QString msSinceEpochToTime(qint64 t1, qint64 t2, qint64 t3 = -1); + Derived *derived() { return static_cast(this); } + const Derived *derived() const { return static_cast(this); } + mutable QReadWriteLock m_lockLogs; //!< lock logging mutable QList m_partsLogs; //!< logs of parts mutable QList m_interpolationLogs; //!< logs of interpolation @@ -210,6 +216,10 @@ namespace BlackMisc private: bool m_supportsParts = false; //!< supports parts for given callsign }; + + //! \cond PRIVATE + extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE CInterpolator; + //! \endcond } // namespace } // namespace #endif // guard diff --git a/src/blackmisc/simulation/interpolatorlinear.cpp b/src/blackmisc/simulation/interpolatorlinear.cpp index 61c1de00e..04a0c5de7 100644 --- a/src/blackmisc/simulation/interpolatorlinear.cpp +++ b/src/blackmisc/simulation/interpolatorlinear.cpp @@ -100,8 +100,8 @@ namespace BlackMisc // do not call for XP (lazy init) if (!hints.hasElevationProvider()) { - IInterpolator::setGroundElevationFromHint(hints, oldSituation, false); - IInterpolator::setGroundElevationFromHint(hints, newSituation, false); + CInterpolator::setGroundElevationFromHint(hints, oldSituation, false); + CInterpolator::setGroundElevationFromHint(hints, newSituation, false); } CAircraftSituation currentSituation(oldSituation); // also sets ground elevation if available diff --git a/src/blackmisc/simulation/interpolatorlinear.h b/src/blackmisc/simulation/interpolatorlinear.h index 69ab7c0ae..c6623c6b3 100644 --- a/src/blackmisc/simulation/interpolatorlinear.h +++ b/src/blackmisc/simulation/interpolatorlinear.h @@ -26,22 +26,24 @@ namespace BlackMisc namespace Simulation { //! Linear interpolator, calculation inbetween positions - class BLACKMISC_EXPORT CInterpolatorLinear : public IInterpolator + class BLACKMISC_EXPORT CInterpolatorLinear : public CInterpolator { + Q_OBJECT + public: //! Constructor CInterpolatorLinear(QObject *parent = nullptr) : - IInterpolator("CInterpolatorLinear", parent) + CInterpolator("CInterpolatorLinear", parent) {} // public base class signature - using IInterpolator::getInterpolatedSituation; + using CInterpolator::getInterpolatedSituation; //! \copydoc IInterpolator::getInterpolatedSituation - virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( + BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituationList &situations, qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetup &setup, - const BlackMisc::Simulation::CInterpolationHints &hints, CInterpolationStatus &status) const override; + const BlackMisc::Simulation::CInterpolationHints &hints, CInterpolationStatus &status) const; //! Log category static QString getLogCategory() { return "swift.interpolatorlinear"; } diff --git a/src/plugins/simulator/fs9/fs9client.h b/src/plugins/simulator/fs9/fs9client.h index 08e17708e..781019dbf 100644 --- a/src/plugins/simulator/fs9/fs9client.h +++ b/src/plugins/simulator/fs9/fs9client.h @@ -50,7 +50,7 @@ namespace BlackSimPlugin void setHostAddress(const QString &hostAddress); //! Get interpolator - BlackMisc::Simulation::IInterpolator *getInterpolator() { return &m_interpolator; } + BlackMisc::Simulation::CInterpolatorLinear *getInterpolator() { return &m_interpolator; } //! Set interpolation setup //! \threadsafe diff --git a/src/plugins/simulator/fsx/simconnectobject.h b/src/plugins/simulator/fsx/simconnectobject.h index 2f7ec3d57..8b905b1ad 100644 --- a/src/plugins/simulator/fsx/simconnectobject.h +++ b/src/plugins/simulator/fsx/simconnectobject.h @@ -16,7 +16,7 @@ #include "simconnectdatadefinition.h" #include -namespace BlackMisc { namespace Simulation { class IInterpolator; } } +namespace BlackMisc { namespace Simulation { class CInterpolatorLinear; } } namespace BlackSimPlugin { namespace Fsx @@ -44,7 +44,7 @@ namespace BlackSimPlugin const QString &getAircraftModelString() const { return m_aircraft.getModelString(); } //! Interpolator - BlackMisc::Simulation::IInterpolator *getInterpolator() const { return m_interpolator.data(); } + BlackMisc::Simulation::CInterpolatorLinear *getInterpolator() const { return m_interpolator.data(); } //! Get current lights (requested from simulator) const BlackMisc::Aviation::CAircraftLights &getCurrentLightsInSimulator() const { return m_currentLightsInSim; } @@ -122,7 +122,7 @@ namespace BlackSimPlugin BlackMisc::Aviation::CAircraftLights m_currentLightsInSim { nullptr }; //!< current lights to know state for toggling BlackMisc::Aviation::CAircraftLights m_lightsAsSent { nullptr }; //!< lights as sent to simulator SIMCONNECT_PERIOD m_requestSimDataPeriod = SIMCONNECT_PERIOD_NEVER; //!< how often do we query ground elevation - QSharedPointer m_interpolator; //!< shared pointer because CSimConnectObject can be copied + QSharedPointer m_interpolator; //!< shared pointer because CSimConnectObject can be copied }; //! Simulator objects (aka AI aircraft) diff --git a/src/xbus/traffic.h b/src/xbus/traffic.h index 2b0a55c48..732428bd2 100644 --- a/src/xbus/traffic.h +++ b/src/xbus/traffic.h @@ -28,14 +28,7 @@ #define XBUS_TRAFFIC_OBJECTPATH "/xbus/traffic" //! \endcond -namespace BlackMisc -{ - namespace Simulation - { - class IInterpolator; - class CInterpolationHints; - } -} +namespace BlackMisc { namespace Simulation { class CInterpolationHints; } } namespace XBus { /*!