diff --git a/client.pro b/client.pro index 2d68f1223..489550d65 100644 --- a/client.pro +++ b/client.pro @@ -47,7 +47,7 @@ equals(WITH_SAMPLES, ON) { SUBDIRS += samples/geodetic2ecef/sample_geodetic2ecef.pro SUBDIRS += samples/interpolator/sample_interpolator.pro SUBDIRS += samples/logging/sample_logging.pro - SUBDIRS += samples/physicalquantities/sample_physicalquantities.pro + SUBDIRS += samples/blackmiscquantities/sample_blackmisc_quantities.pro } equals(WITH_UNITTESTS, ON) { diff --git a/samples/blackmiscquantities/main.cpp b/samples/blackmiscquantities/main.cpp new file mode 100644 index 000000000..dce5eacc2 --- /dev/null +++ b/samples/blackmiscquantities/main.cpp @@ -0,0 +1,19 @@ +#include +#include "samplesphysicalquantities.h" +#include "samplesaviation.h" + +using namespace BlackMisc; +using namespace BlackMiscTest; + +/*! + * Sample tests + */ +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + // CSamplesPhysicalQuantities::samples(); + CSamplesAviation::samples(); + + return a.exec(); +} diff --git a/samples/physicalquantities/sample_physicalquantities.pro b/samples/blackmiscquantities/sample_blackmisc_quantities.pro similarity index 72% rename from samples/physicalquantities/sample_physicalquantities.pro rename to samples/blackmiscquantities/sample_blackmisc_quantities.pro index 06935e5f3..13e2b25f3 100644 --- a/samples/physicalquantities/sample_physicalquantities.pro +++ b/samples/blackmiscquantities/sample_blackmisc_quantities.pro @@ -9,7 +9,9 @@ CONFIG -= app_bundle DEPENDPATH += . ../../src INCLUDEPATH += . ../../src -SOURCES += main.cpp +SOURCES += main.cpp \ + samplesphysicalquantities.cpp \ + samplesaviation.cpp win32-msvc* { PRE_TARGETDEPS += ../../lib/blackmisc.lib @@ -22,3 +24,7 @@ win32-msvc* { } DESTDIR = ../../bin + +HEADERS += \ + samplesphysicalquantities.h \ + samplesaviation.h diff --git a/samples/blackmiscquantities/samplesaviation.cpp b/samples/blackmiscquantities/samplesaviation.cpp new file mode 100644 index 000000000..722647200 --- /dev/null +++ b/samples/blackmiscquantities/samplesaviation.cpp @@ -0,0 +1,23 @@ +#include "samplesaviation.h" + +namespace BlackMiscTest { + +/** + * Samples + */ +int CSamplesAviation::samples() +{ + // CSpeed s1(10, CSpeedUnit::kts()); + CHeading h1(180, true, CAngleUnit::deg()); + CHeading h2(180, false, CAngleUnit::deg()); + qDebug() << h1 << h2 << (h1 == h2) << (h1 != h2) << (h1 == h1); + + CAviationVerticalPositions vp1 = CAviationVerticalPositions::fromAltitudeAndElevationInFt(10000.0, 1111.0); + CAviationVerticalPositions vp2 = vp1; + qDebug() << vp1 << (vp1 == vp2) << (vp1 != vp2); + + // bye + return 0; +} + +} // namespace diff --git a/samples/blackmiscquantities/samplesaviation.h b/samples/blackmiscquantities/samplesaviation.h new file mode 100644 index 000000000..1a9241665 --- /dev/null +++ b/samples/blackmiscquantities/samplesaviation.h @@ -0,0 +1,26 @@ +#ifndef SAMPLESAVIATION_H +#define SAMPLESAVIATION_H + +#include +#include "blackmisc/avheading.h" +#include "blackmisc/avverticalpositions.h" +#include "blackmisc/pqconstants.h" + +using namespace BlackMisc; + +namespace BlackMiscTest { + +/*! + * \brief Samples for physical quantities + */ +class CSamplesAviation +{ +public: + /*! + * \brief Run the samples + */ + static int samples(); +}; +} + +#endif diff --git a/samples/physicalquantities/main.cpp b/samples/blackmiscquantities/samplesphysicalquantities.cpp similarity index 90% rename from samples/physicalquantities/main.cpp rename to samples/blackmiscquantities/samplesphysicalquantities.cpp index 21116cf32..25ce00372 100644 --- a/samples/physicalquantities/main.cpp +++ b/samples/blackmiscquantities/samplesphysicalquantities.cpp @@ -1,20 +1,11 @@ -#include -#include -#include "blackmisc/pqconstants.h" -#include "blackmisc/debug.h" +#include "samplesphysicalquantities.h" -using namespace BlackMisc; +namespace BlackMiscTest { -/*! - * Sample tests - * \brief main - * \param argc - * \param argv - * \return +/** + * Running the quantities */ -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); +int CSamplesPhysicalQuantities::samples() { // cases which must not work // CMeasurementUnit mu; //must not work @@ -100,5 +91,7 @@ int main(int argc, char *argv[]) qDebug() << ti1 << ti2; // bye - return a.exec(); + return 0; } + +} // namespace diff --git a/samples/blackmiscquantities/samplesphysicalquantities.h b/samples/blackmiscquantities/samplesphysicalquantities.h new file mode 100644 index 000000000..b7baac64a --- /dev/null +++ b/samples/blackmiscquantities/samplesphysicalquantities.h @@ -0,0 +1,25 @@ +#ifndef SAMPLESPHYSICALQUANTITIES_H +#define SAMPLESPHYSICALQUANTITIES_H + +#include +#include "blackmisc/pqconstants.h" +#include "blackmisc/debug.h" + +using namespace BlackMisc; + +namespace BlackMiscTest { + +/*! + * \brief Samples for physical quantities + */ +class CSamplesPhysicalQuantities +{ +public: + /*! + * \brief Run the samples + */ + static int samples(); +}; +} + +#endif // SAMPLESPHYSICALQUANTITIES_H diff --git a/src/blackmisc/avaltitude.cpp b/src/blackmisc/avaltitude.cpp new file mode 100644 index 000000000..70ca59660 --- /dev/null +++ b/src/blackmisc/avaltitude.cpp @@ -0,0 +1,42 @@ +#include "avaltitude.h" + +namespace BlackMisc { + +/** + * Own implementation for streaming + */ +QString CAltitude::stringForStreamingOperator() const +{ + QString s = CLength::stringForStreamingOperator(); + return s.append(this->m_msl ? " MSL" : " AGL"); +} + +/** + * Assigment + */ +CAltitude& CAltitude::operator =(const CAltitude &otherAltitude) +{ + // Check for self-assignment! + if (this == &otherAltitude) return *this; + CLength::operator = (otherAltitude); + this->m_msl = otherAltitude.m_msl; + return (*this); +} + +/** + * Equal? + */ +bool CAltitude::operator ==(const CAltitude &otherAltitude) +{ + return otherAltitude.m_msl == this->m_msl && CLength::operator ==(otherAltitude); +} + +/** + * Unequal? + */ +bool CAltitude::operator !=(const CAltitude &otherAltitude) +{ + return !((*this) == otherAltitude); +} + +} // namespace diff --git a/src/blackmisc/avaltitude.h b/src/blackmisc/avaltitude.h new file mode 100644 index 000000000..26071b8df --- /dev/null +++ b/src/blackmisc/avaltitude.h @@ -0,0 +1,88 @@ +#ifndef AVALTITUDE_H +#define AVALTITUDE_H + +#include "blackmisc/pqlength.h" + +namespace BlackMisc { + +/*! + * \brief Altitude as used in aviation, can be AGL or MSL Altitude + * \remarks Intentionally allowing +/- CLength , and >= / <= CLength. + */ +class CAltitude : public CLength +{ +private: + bool m_msl; //!< MSL or AGL? + +protected: + /*! + * \brief Specific stream operation for Altitude + * \return + */ + virtual QString stringForStreamingOperator() const; + +public: + /*! + * \brief Default constructor: 0 Altitude true + */ + CAltitude() : CLength(0, CLengthUnit::m()), m_msl(true) {} + /*! + * \brief Constructor + * \param value + * \param msl MSL or AGL? + * \param unit + */ + CAltitude(double value, bool msl, const CLengthUnit &unit) : CLength(value, unit), m_msl(msl) {} + /*! + * \brief Constructor + * \param value + * \param msl MSL or AGL? + * \param unit + */ + CAltitude(int value, bool msl, const CLengthUnit &unit) : CLength(value, unit), m_msl(msl) {} + /*! + * \brief Constructor by CLength + * \param Altitude + * \param msl + */ + CAltitude(CLength altitude, bool msl) : CLength(), m_msl(msl) { + CLength::operator =(altitude); + } + /*! + * \brief Copy constructor + * \param otherAltitude + */ + CAltitude(const CAltitude &otherAltitude) : CLength(otherAltitude), m_msl(otherAltitude.m_msl) {} + /*! + * \brief Assignment operator = + * \param otherQuantity + * @return + */ + CAltitude &operator =(const CAltitude &otherAltitude); + /*! + * \brief Equal operator == + * \param otherQuantity + * @return + */ + bool operator ==(const CAltitude &otherAltitude); + /*! + * \brief Unequal operator == + * \param otherQuantity + * @return + */ + bool operator !=(const CAltitude &otherAltitude); + /*! + * \brief AGL Above ground level? + * \return + */ + bool isAboveGroundLevel() const { return !this->m_msl; } + /*! + * \brief MSL Mean sea level? + * \return + */ + bool isMeanSeaLevel() const { return this->m_msl; } +}; + +} // namespace + +#endif // AVALTITUDE_H diff --git a/src/blackmisc/avheading.cpp b/src/blackmisc/avheading.cpp new file mode 100644 index 000000000..38f5ebbb7 --- /dev/null +++ b/src/blackmisc/avheading.cpp @@ -0,0 +1,42 @@ +#include "avheading.h" + +namespace BlackMisc { + +/** + * Own implementation for streaming + */ +QString CHeading::stringForStreamingOperator() const +{ + QString s = CAngle::stringForStreamingOperator(); + return s.append(this->m_magnetic ? " magnetic" : " true"); +} + +/** + * Assigment + */ +CHeading& CHeading::operator =(const CHeading &otherHeading) +{ + // Check for self-assignment! + if (this == &otherHeading) return *this; + CAngle::operator = (otherHeading); + this->m_magnetic = otherHeading.m_magnetic; + return (*this); +} + +/** + * Equal? + */ +bool CHeading::operator ==(const CHeading &otherHeading) +{ + return otherHeading.m_magnetic == this->m_magnetic && CAngle::operator ==(otherHeading); +} + +/** + * Unequal? + */ +bool CHeading::operator !=(const CHeading &otherHeading) +{ + return !((*this) == otherHeading); +} + +} // namespace diff --git a/src/blackmisc/avheading.h b/src/blackmisc/avheading.h new file mode 100644 index 000000000..9903710f1 --- /dev/null +++ b/src/blackmisc/avheading.h @@ -0,0 +1,86 @@ +#ifndef AVHEADING_H +#define AVHEADING_H +#include "blackmisc/pqangle.h" + +namespace BlackMisc { + +/*! + * \brief Heading as used in aviation, can be true or magnetic heading + * \remarks Intentionally allowing +/- CAngle , and >= / <= CAngle. + */ +class CHeading : public CAngle +{ +private: + bool m_magnetic; //!< magnetic or true heading? + +protected: + /*! + * \brief Specific stream operation for heading + * \return + */ + virtual QString stringForStreamingOperator() const; + +public: + /*! + * \brief Default constructor: 0 heading true + */ + CHeading() : CAngle(0, CAngleUnit::rad()), m_magnetic(true) {} + /*! + * \brief Constructor + * \param value + * \param magnetic + * \param unit + */ + CHeading(double value, bool magnetic, const CAngleUnit &unit) : CAngle(value, unit), m_magnetic(magnetic) {} + /*! + * \brief Constructor + * \param value + * \param magnetic + * \param unit + */ + CHeading(int value, bool magnetic, const CAngleUnit &unit) : CAngle(value, unit), m_magnetic(magnetic) {} + /*! + * \brief Constructor by CAngle + * \param heading + * \param magnetic + */ + CHeading(CAngle heading, bool magnetic) : CAngle(), m_magnetic(magnetic) { + CAngle::operator =(heading); + } + /*! + * \brief Copy constructor + * \param otherHeading + */ + CHeading(const CHeading &otherHeading) : CAngle(otherHeading), m_magnetic(otherHeading.m_magnetic) {} + /*! + * \brief Assignment operator = + * \param otherQuantity + * @return + */ + CHeading &operator =(const CHeading &otherHeading); + /*! + * \brief Equal operator == + * \param otherQuantity + * @return + */ + bool operator ==(const CHeading &otherHeading); + /*! + * \brief Unequal operator == + * \param otherQuantity + * @return + */ + bool operator !=(const CHeading &otherHeading); + /*! + * \brief Magnetic heading? + * \return + */ + bool isMagneticHeading() const { return this->m_magnetic; } + /*! + * \brief True heading? + * \return + */ + bool isTrueHeading() const { return !this->m_magnetic; } +}; + +} // namespace +#endif // AVHEADING_H diff --git a/src/blackmisc/avtrack.cpp b/src/blackmisc/avtrack.cpp new file mode 100644 index 000000000..1bd87560b --- /dev/null +++ b/src/blackmisc/avtrack.cpp @@ -0,0 +1,42 @@ +#include "avtrack.h" + +namespace BlackMisc { + +/** + * Own implementation for streaming + */ +QString CTrack::stringForStreamingOperator() const +{ + QString s = CAngle::stringForStreamingOperator(); + return s.append(this->m_magnetic ? " magnetic" : " true"); +} + +/** + * Assigment + */ +CTrack& CTrack::operator =(const CTrack &otherTrack) +{ + // Check for self-assignment! + if (this == &otherTrack) return *this; + CAngle::operator = (otherTrack); + this->m_magnetic = otherTrack.m_magnetic; + return (*this); +} + +/** + * Equal? + */ +bool CTrack::operator ==(const CTrack &otherTrack) +{ + return otherTrack.m_magnetic == this->m_magnetic && CAngle::operator ==(otherTrack); +} + +/** + * Unequal? + */ +bool CTrack::operator !=(const CTrack &otherTrack) +{ + return !((*this) == otherTrack); +} + +} // namespace diff --git a/src/blackmisc/avtrack.h b/src/blackmisc/avtrack.h new file mode 100644 index 000000000..bfbd13512 --- /dev/null +++ b/src/blackmisc/avtrack.h @@ -0,0 +1,87 @@ +#ifndef AVTRACK_H +#define AVTRACK_H +#include "blackmisc/pqangle.h" + +namespace BlackMisc { + +/*! + * \brief Track as used in aviation, can be true or magnetic Track + * \remarks Intentionally allowing +/- CAngle , and >= / <= CAngle. + */ +class CTrack : public CAngle +{ +private: + bool m_magnetic; //!< magnetic or true Track? + +protected: + /*! + * \brief Specific stream operation for Track + * \return + */ + virtual QString stringForStreamingOperator() const; + +public: + /*! + * \brief Default constructor: 0 Track true + */ + CTrack() : CAngle(0, CAngleUnit::rad()), m_magnetic(true) {} + /*! + * \brief Constructor + * \param value + * \param magnetic + * \param unit + */ + CTrack(double value, bool magnetic, const CAngleUnit &unit) : CAngle(value, unit), m_magnetic(magnetic) {} + /*! + * \brief Constructor + * \param value + * \param magnetic + * \param unit + */ + CTrack(int value, bool magnetic, const CAngleUnit &unit) : CAngle(value, unit), m_magnetic(magnetic) {} + /*! + * \brief Constructor by CAngle + * \param Track + * \param magnetic + */ + CTrack(CAngle track, bool magnetic) : CAngle(), m_magnetic(magnetic) { + CAngle::operator =(track); + } + /*! + * \brief Copy constructor + * \param otherTrack + */ + CTrack(const CTrack &otherTrack) : CAngle(otherTrack), m_magnetic(otherTrack.m_magnetic) {} + /*! + * \brief Assignment operator = + * \param otherQuantity + * @return + */ + CTrack &operator =(const CTrack &otherTrack); + /*! + * \brief Equal operator == + * \param otherQuantity + * @return + */ + bool operator ==(const CTrack &otherTrack); + /*! + * \brief Unequal operator == + * \param otherQuantity + * @return + */ + bool operator !=(const CTrack &otherTrack); + /*! + * \brief Magnetic Track? + * \return + */ + bool isMagneticTrack() const { return this->m_magnetic; } + /*! + * \brief True Track? + * \return + */ + bool isTrueTrack() const { return !this->m_magnetic; } +}; + +} // namespace + +#endif // AVTRACK_H diff --git a/src/blackmisc/avverticalposition.cpp b/src/blackmisc/avverticalposition.cpp deleted file mode 100644 index 66544e83c..000000000 --- a/src/blackmisc/avverticalposition.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "avverticalposition.h" - -namespace BlackMisc { - -/** - * @brief Default constructor - */ -CAviationVerticalPosition::CAviationVerticalPosition() :m_elevation(CAviationVerticalPosition::valueNotSet()), m_height(CAviationVerticalPosition::valueNotSet()), m_altitude(CAviationVerticalPosition::valueNotSet()) -{ - // void -} - -/** - * Constructor - */ -CAviationVerticalPosition::CAviationVerticalPosition(const CLength &height, const CLength &elevation, const CLength &altitude) : m_height(height), m_elevation(elevation), m_altitude(altitude) -{ - // void -} -} diff --git a/src/blackmisc/avverticalposition.h b/src/blackmisc/avverticalposition.h deleted file mode 100644 index 475303b8e..000000000 --- a/src/blackmisc/avverticalposition.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef AVLATERALPOSITION_H -#define AVLATERALPOSITION_H -#include "blackmisc/pqlength.h" - -namespace BlackMisc { - -/*! - * \brief Vertical (Z) position of an aircraft - */ -class CAviationVerticalPosition -{ -private: - CLength m_height; //!< height - CLength m_elevation; //!< elevation - CLength m_altitude; //!< altitude - -public: - /*! - * \brief Default constructor - */ - CAviationVerticalPosition(); - /*! - * \brief Constructor - * \param height - * \param elevation - * \param altitude - */ - CAviationVerticalPosition(const CLength &height, const CLength &elevation, const CLength &altitude); - /*! - * \brief Value isnot set - * \return - */ - static const CLength& valueNotSet() { static CLength notSet(-1, CLengthUnit::m()); return notSet;} - /*! - * \brief Factory method for convenience if only one component is available - * \param initValue - * \return - */ - static CAviationVerticalPosition getHeight(const CLength &initValue) { return CAviationVerticalPosition(initValue, CAviationVerticalPosition::valueNotSet(), CAviationVerticalPosition::valueNotSet());} - /*! - * \brief Factory method for convenience if only one component is available - * \param initValue - * \return - */ - static CAviationVerticalPosition getElevation(const CLength &initValue) { return CAviationVerticalPosition(CAviationVerticalPosition::valueNotSet(), initValue, CAviationVerticalPosition::valueNotSet());} - /*! - * \brief Factory method for convenience if only one component is available - * \param initValue - * \return - */ - static CAviationVerticalPosition getAltitude(const CLength &initValue) { return CAviationVerticalPosition(CAviationVerticalPosition::valueNotSet(), CAviationVerticalPosition::valueNotSet(), initValue);} - -}; -} // namespace - -#endif // AVLATERALPOSITION_H diff --git a/src/blackmisc/avverticalpositions.cpp b/src/blackmisc/avverticalpositions.cpp new file mode 100644 index 000000000..814e464a6 --- /dev/null +++ b/src/blackmisc/avverticalpositions.cpp @@ -0,0 +1,118 @@ +#include "avverticalpositions.h" + +namespace BlackMisc { + +/** + * Constructor + */ +CAviationVerticalPositions::CAviationVerticalPositions() : + m_altitude(CAltitude(0, true, CLengthUnit::ft())), + m_height(CPhysicalQuantitiesConstants::Length0ft()), + m_elevation(CPhysicalQuantitiesConstants::Length0ft()) +{ + // void +} + +/** + * Constructor + */ +CAviationVerticalPositions::CAviationVerticalPositions(const CAltitude &altitude, const CLength &elevation, const CLength &height) : + m_altitude(altitude), m_elevation(elevation), m_height(height) +{ + // void +} + +/** + * Copy constructor + */ +CAviationVerticalPositions::CAviationVerticalPositions(const CAviationVerticalPositions &otherPosition) : + m_altitude(otherPosition.m_altitude), m_elevation(otherPosition.m_elevation), m_height(otherPosition.m_height) +{ + // void +} + +/** + * Assigment + */ +CAviationVerticalPositions &CAviationVerticalPositions::operator =(const CAviationVerticalPositions &otherPositions) +{ + if (this == &otherPositions) return *this; // Same object? + this->m_altitude = otherPositions.m_altitude; + this->m_elevation = otherPositions.m_elevation; + this->m_height= otherPositions.m_height; + return *this; +} + +/** + * Equal operator + */ +bool CAviationVerticalPositions::operator ==(const CAviationVerticalPositions &otherPositions) +{ + return this->m_altitude == otherPositions.m_altitude && + this->m_elevation == otherPositions.m_elevation && + this->m_height == otherPositions.m_height; +} + +/** + * Unequal operator + */ +bool CAviationVerticalPositions::operator !=(const CAviationVerticalPositions &otherPositions) +{ + return !(*this == otherPositions); +} + +/** + * String representation for streaming + */ +QString CAviationVerticalPositions::stringForStreamingOperator() const +{ + QString s = QString("Altitude: "). + append(this->m_altitude.unitValueRoundedWithUnit()). + append(" Elevation: "). + append(this->m_elevation.unitValueRoundedWithUnit()). + append(" Height: "). + append(this->m_height.unitValueRoundedWithUnit()); + return s; +} + +/** + * Factory by elevation and altitude + */ +CAviationVerticalPositions CAviationVerticalPositions::fromAltitudeAndElevationInFt(double altitudeMslFt, double elevationFt) +{ + CAltitude a(altitudeMslFt, true, CLengthUnit::ft()); + CLength e(elevationFt, CLengthUnit::ft()); + CLength h(altitudeMslFt-elevationFt,CLengthUnit::ft()); + return CAviationVerticalPositions(a, e, h); +} + +/** + * Factory by elevation and altitude + */ +CAviationVerticalPositions CAviationVerticalPositions::fromAltitudeAndElevationInM(double altitudeMslM, double elevationM) +{ + CAltitude a(altitudeMslM, true, CLengthUnit::m()); + CLength e(elevationM, CLengthUnit::m()); + CLength h(altitudeMslM-elevationM,CLengthUnit::m()); + return CAviationVerticalPositions(a, e, h); +} + +/** + * Stream for log message + */ +CLogMessage operator <<(CLogMessage log, const CAviationVerticalPositions &positions) +{ + log << positions.stringForStreamingOperator(); + return log; +} + +/** + * Stream for qDebug + */ +QDebug operator <<(QDebug d, const CAviationVerticalPositions &positions) +{ + d << positions.stringForStreamingOperator(); + return d; +} +} + diff --git a/src/blackmisc/avverticalpositions.h b/src/blackmisc/avverticalpositions.h new file mode 100644 index 000000000..8d9596779 --- /dev/null +++ b/src/blackmisc/avverticalpositions.h @@ -0,0 +1,110 @@ +#ifndef AVLATERALPOSITION_H +#define AVLATERALPOSITION_H +#include "blackmisc/avaltitude.h" +#include "blackmisc/pqconstants.h" + +namespace BlackMisc { + +/*! + * \brief Vertical (Z) positions of an aircraft + */ +class CAviationVerticalPositions +{ + /*! + * \brief Stream << overload to be used in debugging messages + * \param d + * \param unit + * \return + */ + friend QDebug operator<<(QDebug d, const CAviationVerticalPositions &positions); + + /*! + * Stream operator for log messages + * \brief operator << + * \param log + * \param unit + * \return + */ + friend CLogMessage operator<<(CLogMessage log, const CAviationVerticalPositions &positions); + +private: + CLength m_height; //!< height + CLength m_elevation; //!< elevation + CAltitude m_altitude; //!< altitude + +protected: + /*! + * \brief Specific stream operation for heading + * \return + */ + virtual QString stringForStreamingOperator() const; + +public: + /*! + * \brief Default constructor + */ + CAviationVerticalPositions(); + /*! + * \brief Constructor + * \param altitude + * \param elevation + * \param height + */ + CAviationVerticalPositions(const CAltitude &altitude, const CLength &elevation, const CLength &height); + /*! + * \brief Copy constructor + * \param otherPosition + */ + CAviationVerticalPositions(const CAviationVerticalPositions &otherPosition); + /*! + * \brief Assignment operator = + * \param otherQuantity + * @return + */ + CAviationVerticalPositions &operator =(const CAviationVerticalPositions &otherPositions); + /*! + * \brief Equal operator == + * \param otherQuantity + * @return + */ + bool operator ==(const CAviationVerticalPositions &otherPositions); + /*! + * \brief Unequal operator == + * \param otherQuantity + * @return + */ + bool operator !=(const CAviationVerticalPositions &otherPositions); + /*! + * \brief Height + * \return + */ + CLength getHeight() const { return this->m_height;} + /*! + * \brief Elevation + * \return + */ + CLength getElevation() const { return this->m_elevation;} + /*! + * \brief Altitude + * \return + */ + CAltitude getAltitude()const { return this->m_altitude; } + /*! + * \brief Factory getting tupel frome levation and altitude values in ft + * \param altitudeMslFt + * \param elevationFt + * \return + */ + static CAviationVerticalPositions fromAltitudeAndElevationInFt(double altitudeMslFt, double elevationFt); + /*! + * \brief Factory getting tupel frome levation and altitude values in meters + * \param altitudeMslM + * \param elevationM + * \return + */ + static CAviationVerticalPositions fromAltitudeAndElevationInM(double altitudeMslM, double elevationM); +}; + +} // namespace + +#endif // AVLATERALPOSITION_H diff --git a/src/blackmisc/blackmisc.pro b/src/blackmisc/blackmisc.pro index 3147c4a5d..031b03570 100644 --- a/src/blackmisc/blackmisc.pro +++ b/src/blackmisc/blackmisc.pro @@ -45,11 +45,14 @@ HEADERS += \ pqpressure.h \ pqtemperature.h \ pqconstants.h \ - avverticalposition.h \ pqunits.h \ pqallquantities.h \ pqlength.h \ - pqtime.h + pqtime.h \ + avheading.h \ + avtrack.h \ + avaltitude.h \ + avverticalpositions.h SOURCES += \ logmessage.cpp \ @@ -73,6 +76,9 @@ SOURCES += \ pqphysicalquantity.cpp \ pqbase.cpp \ pqunits.cpp \ - avverticalposition.cpp + avheading.cpp \ + avtrack.cpp \ + avaltitude.cpp \ + avverticalpositions.cpp DESTDIR = ../../lib diff --git a/src/blackmisc/pqbase.cpp b/src/blackmisc/pqbase.cpp index decba45fc..e3c0e1689 100644 --- a/src/blackmisc/pqbase.cpp +++ b/src/blackmisc/pqbase.cpp @@ -215,4 +215,15 @@ double CMeasurementUnit::round(double value, int digits) { return rv; } +/*! + * Epsilon rounding + */ +double CMeasurementUnit::epsilonRounding(double value) const +{ + // does notwork reliable with qRound for some reason + double v = floor((value + this->m_epsilon) / this->m_epsilon); + v *=this->m_epsilon; + return v; +} + } // namespace diff --git a/src/blackmisc/pqbase.h b/src/blackmisc/pqbase.h index 8ae6db707..75ad05c34 100644 --- a/src/blackmisc/pqbase.h +++ b/src/blackmisc/pqbase.h @@ -187,7 +187,7 @@ private: bool m_isSIBaseUnit; //!< SI base unit? double m_conversionFactorToSIConversionUnit; //!< factor to convert to SI, set to 0 if not applicable (rare cases, e.g. temperature) double m_epsilon; //!< values with differences below epsilon are the equal - qint32 m_displayDigits; //!< standard rounding dor string conversions + qint32 m_displayDigits; //!< standard rounding for string conversions CMeasurementPrefix m_multiplier; //!< multiplier (kilo, Mega) protected: @@ -333,6 +333,15 @@ public: * \return */ static double round(double value, int digits); + + /*! + * Epsilon rounding. In some conversion rouding is required to avoid + * periodical numbers. + * \param value + * \return + */ + double epsilonRounding(double value) const; + /*! * \brief Unit is not specified * \return diff --git a/src/blackmisc/pqconstants.h b/src/blackmisc/pqconstants.h index 29eb5cb64..62ef417d4 100644 --- a/src/blackmisc/pqconstants.h +++ b/src/blackmisc/pqconstants.h @@ -29,6 +29,16 @@ public: * \return */ static const CPressure& InternationalStandardSeaLevelPressure() { static CPressure p(1013.25, CPressureUnit::hPa()); return p;} + /*! + * \brief 0m + * \return + */ + static const CLength& Length0m() { static CLength l(0, CLengthUnit::m()); return l;} + /*! + * \brief 0ft + * \return + */ + static const CLength& Length0ft() { static CLength l(0, CLengthUnit::ft()); return l;} }; } // namespace #endif // PQCONSTANTS_H diff --git a/src/blackmisc/pqmass.h b/src/blackmisc/pqmass.h index b7bdef6f3..e2e0cf3cc 100644 --- a/src/blackmisc/pqmass.h +++ b/src/blackmisc/pqmass.h @@ -1,6 +1,6 @@ #ifndef PQMASS_H #define PQMASS_H -#include "pqphysicalquantity.h" +#include "blackmisc/pqphysicalquantity.h" namespace BlackMisc { diff --git a/src/blackmisc/pqphysicalquantity.cpp b/src/blackmisc/pqphysicalquantity.cpp index 579a3a15c..77edb80b6 100644 --- a/src/blackmisc/pqphysicalquantity.cpp +++ b/src/blackmisc/pqphysicalquantity.cpp @@ -79,7 +79,7 @@ template bool CPhysicalQuantity::operator !=(const C template CPhysicalQuantity& CPhysicalQuantity::operator=(const CPhysicalQuantity &otherQuantity) { // Check for self-assignment! - if (this == &otherQuantity) return *this; // Same object? Yes, so skip assignment, and just return *this + if (this == &otherQuantity) return *this; // Same object? this->m_unitValueI = otherQuantity.m_unitValueI; this->m_unitValueD = otherQuantity.m_unitValueD; @@ -280,7 +280,8 @@ template void CPhysicalQuantity::setUnitValue(double * Set SI value */ template void CPhysicalQuantity::setConversionSiUnitValue() { - this->m_convertedSiUnitValueD = this->m_unit.convertToSiConversionUnit(this->m_unitValueD); + double si = this->m_unit.convertToSiConversionUnit(this->m_unitValueD); + this->m_convertedSiUnitValueD = si; } /** diff --git a/src/blackmisc/pqphysicalquantity.h b/src/blackmisc/pqphysicalquantity.h index a5eb5c268..d541af155 100644 --- a/src/blackmisc/pqphysicalquantity.h +++ b/src/blackmisc/pqphysicalquantity.h @@ -1,7 +1,6 @@ #ifndef PQPHYSICALQUANTITY_H #define PQPHYSICALQUANTITY_H - #include #include #include @@ -11,20 +10,12 @@ namespace BlackMisc { -class CAngle; - /*! * \brief A physical quantity such as "5m", "20s", "1500ft/s" * \author KWB */ template class CPhysicalQuantity { - /*! - * Our converter function, should be implemented as static method of the quantity - * classes for clarity - */ - typedef double (*CPhysicalQuantityUnitConverter)(const PQ *quantity, const MU &unit); - /*! * Stream operator for debugging * \brief operator << @@ -34,7 +25,7 @@ template class CPhysicalQuantity * \remarks Has to be in the header files to avoid template link errors */ friend QDebug operator<<(QDebug debug, const CPhysicalQuantity &quantity) { - QString v = quantity.unitValueRoundedWithUnit(-1); + QString v = quantity.stringForStreamingOperator(); debug << v; return debug; } @@ -45,10 +36,10 @@ template class CPhysicalQuantity * \param log * \param quantity * \return - * \remarks Has to be in the header files toavoid templatelink errors + * \remarks Has to be in the header files to avoid template link errors */ friend CLogMessage operator<<(CLogMessage log, const CPhysicalQuantity &quantity) { - QString v = quantity.unitValueRoundedWithUnit(-1); + QString v = quantity.stringForStreamingOperator(); log << v; return log; } @@ -62,6 +53,11 @@ private: protected: MU m_unit; //!< unit MU m_conversionSiUnit; //!< corresponding SI base unit + /*! + * \brief String for streaming operators + * \return + */ + virtual QString stringForStreamingOperator() const { return this->unitValueRoundedWithUnit(-1); } /*! * \brief Constructor with int @@ -232,10 +228,6 @@ public: * \param value */ void substractUnitValue(double value); - /*! - * \brief Cast as double - */ - operator double() const { return this->m_convertedSiUnitValueD; } /*! * \brief Cast as QString */ @@ -334,6 +326,6 @@ public: }; -} // namespace BlackCore +} // namespace #endif // PQPHYSICALQUANTITY_H diff --git a/src/blackmisc/pqunits.cpp b/src/blackmisc/pqunits.cpp index 715256ac3..e91401710 100644 --- a/src/blackmisc/pqunits.cpp +++ b/src/blackmisc/pqunits.cpp @@ -31,7 +31,9 @@ double CAngleUnit::convertFromSiConversionUnit(double value) const // still a design flaw since I have to distinguish as per type // but an own converter per object was really too much if ((*this) == CAngleUnit::sexagesimalDeg()) { - value = value * 180 / M_PI; // degree + // using rounding here, since fractions can lead to ugly sexagesimal conversion + // e.g. 185.499999 gives 185 29' 59.9999" + value = this->epsilonRounding(value * 180 / M_PI); // degree v = floor(value); double c = value - v; double mr = c * 60.0; @@ -75,6 +77,7 @@ QString CAngleUnit::toQStringRounded(double value, int digits) const { QString s; if ((*this) == CAngleUnit::sexagesimalDeg()) { + // special formatting for sexagesimal degrees double de = floor(value); double mi = floor((value-de)*100.0); double se = floor((value-de-mi/100.0)*1000000) / 100.0; diff --git a/src/blackmisc/pqunits.h b/src/blackmisc/pqunits.h index f4be9ffdb..3929db710 100644 --- a/src/blackmisc/pqunits.h +++ b/src/blackmisc/pqunits.h @@ -377,9 +377,14 @@ public: * \brief Meter/second m/s * \return */ - static const CSpeedUnit& m_s() { static CSpeedUnit ms("meter/second", "m/s", true, false); return ms;} + static const CSpeedUnit& m_s() { static CSpeedUnit ms("meters/second", "m/s", true, false); return ms;} /*! - * \brief Nautical miles per hour NM/h + * \brief Knots + * \return + */ + static const CSpeedUnit& kts() { static CSpeedUnit kts("knot", "kts", false, false, 1852.0/3600.0, CMeasurementPrefix::One(), 1);return kts;} + /*! + * \brief Nautical miles per hour NM/h (same as kts) * \return */ static const CSpeedUnit& NM_h() { static CSpeedUnit NMh("nautical miles/hour", "NM/h", false, false, 1852.0/3600.0, CMeasurementPrefix::One(), 1);return NMh;} @@ -397,7 +402,7 @@ public: * \brief Kilometer/hour km/h * \return */ - static const CSpeedUnit& km_h() { static CSpeedUnit kmh("kilometer/hour", "km/h", false, false, 1.0/3.6, CMeasurementPrefix::One(), 1);return kmh;} + static const CSpeedUnit& km_h() { static CSpeedUnit kmh("kilometers/hour", "km/h", false, false, 1.0/3.6, CMeasurementPrefix::One(), 1);return kmh;} }; /*! diff --git a/tests/blackmisc/main.cpp b/tests/blackmisc/main.cpp index 6f562ba88..691e96e88 100644 --- a/tests/blackmisc/main.cpp +++ b/tests/blackmisc/main.cpp @@ -14,7 +14,7 @@ using namespace BlackMiscTest; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); - TestMain::unitMain(argc, argv); + CTestMain::unitMain(argc, argv); // bye return a.exec(); diff --git a/tests/blackmisc/test_blackmisc.pro b/tests/blackmisc/test_blackmisc.pro index 21f3a453a..893844d2d 100644 --- a/tests/blackmisc/test_blackmisc.pro +++ b/tests/blackmisc/test_blackmisc.pro @@ -9,9 +9,14 @@ CONFIG -= app_bundle DEPENDPATH += . ../../src INCLUDEPATH += . ../../src -SOURCES += main.cpp testmain.cpp testphysicalquantitiesbase.cpp -HEADERS += testmain.h testphysicalquantitiesbase.h \ - blackmisctest.h +SOURCES += main.cpp testmain.cpp \ + testphysicalquantitiesbase.cpp \ + testaviationbase.cpp + +HEADERS += testmain.h \ + testphysicalquantitiesbase.h \ + blackmisctest.h \ + testaviationbase.h win32-msvc* { PRE_TARGETDEPS += ../../lib/blackmisc.lib diff --git a/tests/blackmisc/testaviationbase.cpp b/tests/blackmisc/testaviationbase.cpp new file mode 100644 index 000000000..351f0d751 --- /dev/null +++ b/tests/blackmisc/testaviationbase.cpp @@ -0,0 +1,47 @@ +#include "testaviationbase.h" + +namespace BlackMiscTest { + +/** + * Constructor + */ +CTestAviationBase::CTestAviationBase(QObject *parent): QObject(parent) +{ + // void +} + +/** + * Basic tests + */ +void CTestAviationBase::headingBasics() +{ + CHeading h1(180, true, CAngleUnit::deg()); + CHeading h2(180, false, CAngleUnit::deg()); + CHeading h3(181, true, CAngleUnit::deg()); + CAngle a1(200,CAngleUnit::deg()); + CHeading h4; + h4 = h1; + QVERIFY2(h1 != h2, "Magnetic and true heading are not the same"); + QVERIFY2(h1 < h3, "180deg are less than 181deg"); + QVERIFY2(a1 > h3, "200deg are more than 200deg"); + QVERIFY2(h4 == h1, "Values shall be equal"); + + h1 -= h1; + QVERIFY2(h1.unitValueToDouble() == 0, "Value shall be 0"); + + // h4 = h1 + h2; does not work, because misleading + h2 += h2; // add just angle + QVERIFY2(h2.unitValueToDouble() == 360, "Value shall be 360"); +} + +/** + * Vertical positions + */ +void CTestAviationBase::verticalPosition() +{ + CAviationVerticalPositions vp1 = CAviationVerticalPositions::fromAltitudeAndElevationInFt(10000.0, 3000.0); + CAviationVerticalPositions vp2 = vp1; + QVERIFY2(vp1== vp2, "Values shall be equal"); +} + +} // namespace diff --git a/tests/blackmisc/testaviationbase.h b/tests/blackmisc/testaviationbase.h new file mode 100644 index 000000000..ca42b04b9 --- /dev/null +++ b/tests/blackmisc/testaviationbase.h @@ -0,0 +1,41 @@ +#ifndef TESTAVIATIONBASE_H +#define TESTAVIATIONBASE_H + +#include +#include "blackmisc/pqconstants.h" +#include "blackmisc/avheading.h" +#include "blackmisc/avverticalpositions.h" +using namespace BlackMisc; + +namespace BlackMiscTest { + +/*! + * \brief Aviation classes basic tests + */ +class CTestAviationBase : public QObject +{ + Q_OBJECT + +public: + /*! + * \brief Standard test case constructor + * \param parent + */ + explicit CTestAviationBase(QObject *parent = 0); + +private slots: + /*! + * \brief Basic unit tests for physical units + */ + void headingBasics(); + + /*! + * \brief Vertical positions + */ + void verticalPosition(); + +}; + +} // namespace + +#endif // TESTAVIATIONBASE_H diff --git a/tests/blackmisc/testmain.cpp b/tests/blackmisc/testmain.cpp index 318fb9f17..9db0be2f1 100644 --- a/tests/blackmisc/testmain.cpp +++ b/tests/blackmisc/testmain.cpp @@ -7,12 +7,14 @@ namespace BlackMiscTest { \param argv \sa http://stackoverflow.com/questions/12194256/qt-how-to-organize-unit-test-with-more-than-one-class */ -int TestMain::unitMain(int argc, char *argv[]) +int CTestMain::unitMain(int argc, char *argv[]) { int status = 0; { - TestPhysicalQuantitiesBase pqBaseTests ; + CTestPhysicalQuantitiesBase pqBaseTests ; + CTestAviationBase avBaseTests; status |= QTest::qExec(&pqBaseTests, argc, argv); + status |= QTest::qExec(&avBaseTests, argc, argv); } return status; } diff --git a/tests/blackmisc/testmain.h b/tests/blackmisc/testmain.h index cc581f154..a1d8473ed 100644 --- a/tests/blackmisc/testmain.h +++ b/tests/blackmisc/testmain.h @@ -3,6 +3,7 @@ #include #include "testphysicalquantitiesbase.h" +#include "testaviationbase.h" namespace BlackMiscTest{ @@ -11,7 +12,7 @@ namespace BlackMiscTest{ * Avoids clashes with other main(..) functions and allows to fire the test cases * simply from any other main. */ -class TestMain +class CTestMain { public: static int unitMain(int argc, char *argv[]); diff --git a/tests/blackmisc/testphysicalquantitiesbase.cpp b/tests/blackmisc/testphysicalquantitiesbase.cpp index 9e7274a43..3ad129f51 100644 --- a/tests/blackmisc/testphysicalquantitiesbase.cpp +++ b/tests/blackmisc/testphysicalquantitiesbase.cpp @@ -3,10 +3,9 @@ namespace BlackMiscTest { /*! - * \brief Constructor - * \param parent + * Constructor */ -TestPhysicalQuantitiesBase::TestPhysicalQuantitiesBase(QObject *parent) : QObject(parent) +CTestPhysicalQuantitiesBase::CTestPhysicalQuantitiesBase(QObject *parent) : QObject(parent) { // void } @@ -14,7 +13,7 @@ TestPhysicalQuantitiesBase::TestPhysicalQuantitiesBase(QObject *parent) : QObjec /*! * Basic unit tests for physical units */ -void TestPhysicalQuantitiesBase::unitsBasics() +void CTestPhysicalQuantitiesBase::unitsBasics() { QVERIFY(CMeasurementPrefix::k() > CMeasurementPrefix::h()); @@ -35,7 +34,7 @@ void TestPhysicalQuantitiesBase::unitsBasics() /*! * Distance tests */ -void TestPhysicalQuantitiesBase::lengthBasics() +void CTestPhysicalQuantitiesBase::lengthBasics() { CLength d1(1,CLengthUnit::m()); // 1m CLength d2(100, CLengthUnit::cm()); @@ -66,7 +65,7 @@ void TestPhysicalQuantitiesBase::lengthBasics() /** * Unit tests for speed */ -void TestPhysicalQuantitiesBase::speedBasics() +void CTestPhysicalQuantitiesBase::speedBasics() { CSpeed s1(100, CSpeedUnit::km_h()); CSpeed s2(1000, CSpeedUnit::ft_min()); @@ -77,11 +76,12 @@ void TestPhysicalQuantitiesBase::speedBasics() /** * Frequency unit tests */ -void TestPhysicalQuantitiesBase::frequencyTests() +void CTestPhysicalQuantitiesBase::frequencyTests() { CFrequency f1(1, CFrequencyUnit::MHz()); QVERIFY2(f1.valueRounded(CFrequencyUnit::kHz(),2) == 1000, "Mega is 1000kHz"); - QVERIFY2(f1 == 1000000 , "MHz is 1E6 Hz"); + QVERIFY2(f1.unitValueToDouble() == 1 , "1MHz"); + QVERIFY2(f1.siBaseUnitValueToDouble() == 1000000 , "1E6 Hz"); CFrequency f2(CMeasurementPrefix::M(),CFrequencyUnit::Hz()) ; // 1 Megahertz QVERIFY2(f1 == f2 , "MHz is 1E6 Hz"); } @@ -89,7 +89,7 @@ void TestPhysicalQuantitiesBase::frequencyTests() /** * Angle tests */ -void TestPhysicalQuantitiesBase::angleTests() +void CTestPhysicalQuantitiesBase::angleTests() { CAngle a1(180, CAngleUnit::deg()); CAngle a2(1.5 * CAngle::pi(), CAngleUnit::rad()); @@ -103,10 +103,10 @@ void TestPhysicalQuantitiesBase::angleTests() /** * Weight tests */ -void TestPhysicalQuantitiesBase::massTests() +void CTestPhysicalQuantitiesBase::massTests() { CMass w1(1000, CMassUnit::kg()); - CMass w2(w1, CMassUnit::kg()); + CMass w2(w1.unitValueToInteger(), CMassUnit::kg()); w2.switchUnit(CMassUnit::t()); QVERIFY2(w2.unitValueToInteger() == 1, "1tonne shall be 1000kg"); w2.switchUnit(CMassUnit::lb()); @@ -117,7 +117,7 @@ void TestPhysicalQuantitiesBase::massTests() /** * Pressure tests */ -void TestPhysicalQuantitiesBase::pressureTests() +void CTestPhysicalQuantitiesBase::pressureTests() { CPressure p1(1013.25, CPressureUnit::hPa()); CPressure p2(29.92,CPressureUnit::inHg()); @@ -134,7 +134,7 @@ void TestPhysicalQuantitiesBase::pressureTests() /** * Temperature tests */ -void TestPhysicalQuantitiesBase::temperatureTests() +void CTestPhysicalQuantitiesBase::temperatureTests() { CTemperature t1(0, CTemperatureUnit::C()); // 0C CTemperature t2(1, CTemperatureUnit::F()); // 1F @@ -149,7 +149,7 @@ void TestPhysicalQuantitiesBase::temperatureTests() /** * Temperature tests */ -void TestPhysicalQuantitiesBase::timeTests() +void CTestPhysicalQuantitiesBase::timeTests() { CTime t1(1, CTimeUnit::h()); QVERIFY2(t1.siBaseUnitValueToInteger() == 3600, "1hour shall be 3600s"); @@ -158,7 +158,7 @@ void TestPhysicalQuantitiesBase::timeTests() /** * Just testing obvious memory create / destruct flaws */ -void TestPhysicalQuantitiesBase::memoryTests() +void CTestPhysicalQuantitiesBase::memoryTests() { CLength* c = new CLength(100, CLengthUnit::m()); c->switchUnit(CLengthUnit::NM()); @@ -176,7 +176,7 @@ void TestPhysicalQuantitiesBase::memoryTests() /** * @brief Just testing obvious memory create / destruct flaws */ -void TestPhysicalQuantitiesBase::basicArithmetic() +void CTestPhysicalQuantitiesBase::basicArithmetic() { CPressure p1 = CPhysicalQuantitiesConstants::InternationalStandardSeaLevelPressure(); CPressure p2(p1); diff --git a/tests/blackmisc/testphysicalquantitiesbase.h b/tests/blackmisc/testphysicalquantitiesbase.h index bccd02482..d015c1a4c 100644 --- a/tests/blackmisc/testphysicalquantitiesbase.h +++ b/tests/blackmisc/testphysicalquantitiesbase.h @@ -10,7 +10,7 @@ namespace BlackMiscTest { /*! * \brief Physical quantities,basic tests */ -class TestPhysicalQuantitiesBase : public QObject +class CTestPhysicalQuantitiesBase : public QObject { Q_OBJECT public: @@ -18,7 +18,7 @@ public: * \brief Standard test case constructor * \param parent */ - explicit TestPhysicalQuantitiesBase(QObject *parent = 0); + explicit CTestPhysicalQuantitiesBase(QObject *parent = 0); private slots: /*! * \brief Basic unit tests for physical units @@ -67,6 +67,6 @@ private slots: }; -} +} // namespace #endif // TESTPHYSICALQUANTITIESBASE_H