From da8ba9aac3c3cd40b512e558a78c1ead38b5ab5b Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 18 Aug 2013 23:40:52 +0100 Subject: [PATCH] First major wave of PQ refactoring, including but not limited to: * Default unit is more clearly stated in one place, not restated in many different places, and is not always the SI unit * Converter strategy pattern in CMeasurementUnit, covering linear, affine, and different kinds of sexagesimal units * General reorganization of CMeasurementUnit construction and CPhysicalQuantity methods, not removing any behvaiour * Move duplicated method unitFromSymbol from derived classes into base class CMeasurementUnit * For DBus, CPhysicalQuantity marshals both in its own unit and in the default unit --- .../samplesphysicalquantities.cpp | 15 +- samples/blackmiscquantities_dbus/main.cpp | 4 +- src/blackmisc/aviomodulator.h | 4 +- src/blackmisc/coordinategeodetic.cpp | 2 +- src/blackmisc/coordinatetransformation.cpp | 2 +- src/blackmisc/geoearthangle.h | 2 +- src/blackmisc/mathematics.h | 21 + src/blackmisc/pqacceleration.h | 4 +- src/blackmisc/pqangle.h | 24 +- src/blackmisc/pqbase.cpp | 110 ++- src/blackmisc/pqbase.h | 380 ++++++----- src/blackmisc/pqconstants.h | 10 + src/blackmisc/pqfrequency.h | 4 +- src/blackmisc/pqlength.h | 4 +- src/blackmisc/pqmass.h | 4 +- src/blackmisc/pqphysicalquantity.cpp | 166 +---- src/blackmisc/pqphysicalquantity.h | 208 ++---- src/blackmisc/pqpressure.h | 4 +- src/blackmisc/pqspeed.h | 4 +- src/blackmisc/pqtemperature.h | 4 +- src/blackmisc/pqtime.h | 4 +- src/blackmisc/pqunits.cpp | 111 ++-- src/blackmisc/pqunits.h | 624 +++++++++--------- tests/blackmisc/testaviation.cpp | 4 +- tests/blackmisc/testgeo.cpp | 2 +- tests/blackmisc/testphysicalquantities.cpp | 45 +- 26 files changed, 809 insertions(+), 957 deletions(-) diff --git a/samples/blackmiscquantities/samplesphysicalquantities.cpp b/samples/blackmiscquantities/samplesphysicalquantities.cpp index ca451855b..322eaa450 100644 --- a/samples/blackmiscquantities/samplesphysicalquantities.cpp +++ b/samples/blackmiscquantities/samplesphysicalquantities.cpp @@ -57,7 +57,7 @@ int CSamplesPhysicalQuantities::samples() CSpeed s2 = CSpeed(1000, CSpeedUnit::ft_min()); CSpeed s3 = CSpeed(s2); s3.switchUnit(CSpeedUnit::m_s()); - qDebug() << s1 << s1.convertedSiValueRoundedWithUnit() << s1.valueRoundedWithUnit(CSpeedUnit::NM_h()); + qDebug() << s1 << s1.valueRoundedWithUnit(CSpeedUnit::defaultUnit()) << s1.valueRoundedWithUnit(CSpeedUnit::NM_h()); qDebug() << s2 << s3; CAngle a1(180, CAngleUnit::deg()); @@ -72,7 +72,7 @@ int CSamplesPhysicalQuantities::samples() a2 = a1 + a1; a2.switchUnit(CAngleUnit::deg()); - qDebug() << a1.unitValueRoundedWithUnit() << a1.piFactor(); + qDebug() << a1.valueRoundedWithUnit() << a1.piFactor(); qDebug() << a2; a3.switchUnit(CAngleUnit::sexagesimalDeg()); a4.switchUnit(CAngleUnit::deg()); @@ -89,8 +89,8 @@ int CSamplesPhysicalQuantities::samples() CTemperature t1; CTemperature t2(20, CTemperatureUnit::C()); CTemperature t3(1, CTemperatureUnit::F()); - qDebug() << t1 << t2 << t2.convertedSiValueRoundedWithUnit(true); - qDebug() << t3.valueRoundedWithUnit(CTemperatureUnit::F(), -1 ,true) << t3.valueRoundedWithUnit(CTemperatureUnit::C(), -1, true) << "I18N/UTF"; + qDebug() << t1 << t2 << t2.valueRoundedWithUnit(CTemperatureUnit::defaultUnit(), -1, true); + qDebug() << t3.valueRoundedWithUnit(CTemperatureUnit::F(), -1, true) << t3.valueRoundedWithUnit(CTemperatureUnit::C(), -1, true) << "I18N/UTF"; // some logging with CLogMessage // bDebug << p1; @@ -108,10 +108,13 @@ int CSamplesPhysicalQuantities::samples() CTime ti1(1, CTimeUnit::h()); CTime ti2(ti1); ti2.switchUnit(CTimeUnit::ms()); - qDebug() << ti1 << ti2; + CTime ti3(1.0101, CTimeUnit::hms()); + CTime ti4(1.15, CTimeUnit::hrmin()); + CTime ti5(1.30, CTimeUnit::minsec()); + qDebug() << ti1 << ti2 << ti3 << ti4 << ti5; CAcceleration ac1(10, CAccelerationUnit::m_s2()); - qDebug() << ac1 << ac1.unitValueRoundedWithUnit(-1, true) << "I18N/UTF"; + qDebug() << ac1 << ac1.valueRoundedWithUnit(-1, true) << "I18N/UTF"; // bye qDebug() << "-----------------------------------------------"; diff --git a/samples/blackmiscquantities_dbus/main.cpp b/samples/blackmiscquantities_dbus/main.cpp index f43989c1a..e88fea442 100644 --- a/samples/blackmiscquantities_dbus/main.cpp +++ b/samples/blackmiscquantities_dbus/main.cpp @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) qDebug() << "Send speed via interface" << speed; TestserviceTool::sleep(2500); speed.switchUnit(CSpeedUnit::km_h()); - speed.addUnitValue(1.0); + speed.addValueSameUnit(1.0); // Aviation CComSystem comSystem = CComSystem("DBUS COM1", CPhysicalQuantitiesConstants::FrequencyInternationalAirDistress(), CPhysicalQuantitiesConstants::FrequencyUnicom()); @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) testserviceInterface.receiveVariant(qv); testserviceInterface.receiveAltitude(al); qDebug() << "Send altitude via interface" << al; - al.addUnitValue(1); + al.addValueSameUnit(1); CTransponder transponder("transponder", 7000, CTransponder::ModeC); testserviceInterface.receiveTransponder(transponder); diff --git a/src/blackmisc/aviomodulator.h b/src/blackmisc/aviomodulator.h index b51686b18..3d6ca3a5a 100644 --- a/src/blackmisc/aviomodulator.h +++ b/src/blackmisc/aviomodulator.h @@ -85,8 +85,8 @@ protected: virtual QString convertToQString(bool i18n = false) const { QString s(this->getName()); - s.append(" Active: ").append(this->m_frequencyActive.unitValueRoundedWithUnit(3, i18n)); - s.append(" Standby: ").append(this->m_frequencyStandby.unitValueRoundedWithUnit(3, i18n)); + s.append(" Active: ").append(this->m_frequencyActive.valueRoundedWithUnit(3, i18n)); + s.append(" Standby: ").append(this->m_frequencyStandby.valueRoundedWithUnit(3, i18n)); return s; } diff --git a/src/blackmisc/coordinategeodetic.cpp b/src/blackmisc/coordinategeodetic.cpp index 10f64507c..b1d675b33 100644 --- a/src/blackmisc/coordinategeodetic.cpp +++ b/src/blackmisc/coordinategeodetic.cpp @@ -16,7 +16,7 @@ namespace Geo QString CCoordinateGeodetic::convertToQString(bool i18n) const { QString s = "Geodetic: {%1, %2, %3}"; - return s.arg(this->m_latitude.unitValueRoundedWithUnit(6, i18n)).arg(this->m_longitude.unitValueRoundedWithUnit(6, i18n)).arg(this->m_height.unitValueRoundedWithUnit(i18n)); + return s.arg(this->m_latitude.valueRoundedWithUnit(6, i18n)).arg(this->m_longitude.valueRoundedWithUnit(6, i18n)).arg(this->m_height.valueRoundedWithUnit(i18n)); } /* diff --git a/src/blackmisc/coordinatetransformation.cpp b/src/blackmisc/coordinatetransformation.cpp index a79483ce9..28c70fbc4 100644 --- a/src/blackmisc/coordinatetransformation.cpp +++ b/src/blackmisc/coordinatetransformation.cpp @@ -80,7 +80,7 @@ CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateGeodetic &geo double clambda = cos(lambdaRad); - double h = geo.height().convertedSiValueToDouble(); + double h = geo.height().value(CLengthUnit::m()); double x = (n + h) * cphi; double y = x * slambda; x *= clambda; diff --git a/src/blackmisc/geoearthangle.h b/src/blackmisc/geoearthangle.h index 54c74a021..ccb707659 100644 --- a/src/blackmisc/geoearthangle.h +++ b/src/blackmisc/geoearthangle.h @@ -75,7 +75,7 @@ protected: */ virtual QString convertToQString() const { - return this->unitValueRoundedWithUnit(6); + return this->valueRoundedWithUnit(6); } /*! diff --git a/src/blackmisc/mathematics.h b/src/blackmisc/mathematics.h index f49241513..fa0eeada8 100644 --- a/src/blackmisc/mathematics.h +++ b/src/blackmisc/mathematics.h @@ -6,6 +6,7 @@ #ifndef BLACKMISC_MATHEMATICS_H #define BLACKMISC_MATHEMATICS_H #include +#include namespace BlackMisc { @@ -70,6 +71,26 @@ public: */ static double roundEpsilon(double value, double epsilon); + /*! + * \brief Nearest integer not greater in magnitude than value, correcting for epsilon + * \param value + * \param epsilon + */ + static inline double trunc(double value, double epsilon = 1e-10) + { + return value < 0 ? ceil(value - epsilon) : floor(value + epsilon); + } + + /*! + * \brief Fractional part of value + * \param value + */ + static inline double fract(double value) + { + double unused; + return modf(value, &unused); + } + /*! * \brief PI * \return diff --git a/src/blackmisc/pqacceleration.h b/src/blackmisc/pqacceleration.h index 0461f8b3f..6d7c7718e 100644 --- a/src/blackmisc/pqacceleration.h +++ b/src/blackmisc/pqacceleration.h @@ -21,14 +21,14 @@ public: /*! * \brief Default constructor */ - CAcceleration() : CPhysicalQuantity(0, CAccelerationUnit::m_s2(), CAccelerationUnit::m_s2()) {} + CAcceleration() : CPhysicalQuantity(0, CAccelerationUnit::defaultUnit()) {} /*! * \brief Init by double value * \param value * \param unit */ - CAcceleration(double value, const CAccelerationUnit &unit) : CPhysicalQuantity(value, unit, CAccelerationUnit::m_s2()) {} + CAcceleration(double value, const CAccelerationUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Copy constructor by base type diff --git a/src/blackmisc/pqangle.h b/src/blackmisc/pqangle.h index 1dc37a270..9453f63c6 100644 --- a/src/blackmisc/pqangle.h +++ b/src/blackmisc/pqangle.h @@ -22,7 +22,7 @@ public: /*! * \brief Default constructor */ - CAngle() : CPhysicalQuantity(0, CAngleUnit::rad(), CAngleUnit::rad()) {} + CAngle() : CPhysicalQuantity(0, CAngleUnit::defaultUnit()) {} /*! * \brief Copy constructor from base type @@ -34,18 +34,30 @@ public: * \param value * \param unit */ - CAngle(double value, const CAngleUnit &unit): CPhysicalQuantity(value, unit, CAngleUnit::rad()) {} + CAngle(double value, const CAngleUnit &unit): CPhysicalQuantity(value, unit) {} /*! - * \brief Intir as sexagesimal degrees + * \brief Init as sexagesimal degrees, minutes, seconds + * The sign of all parameters must be the same, either all positive or all negative. * \param degrees * \param minutes * \param seconds */ - CAngle(qint32 degrees, qint32 minutes, double seconds) : + CAngle(int degrees, int minutes, double seconds) : CPhysicalQuantity( degrees + minutes / 100.0 + seconds / 10000.0, - CAngleUnit::sexagesimalDeg(), CAngleUnit::rad()) {} + CAngleUnit::sexagesimalDeg()) {} + + /*! + * \brief Init as sexagesimal degrees, minutes + * The sign of both parameters must be the same, either both positive or both negative. + * \param degrees + * \param minutes + */ + CAngle(int degrees, double minutes) : + CPhysicalQuantity( + degrees + minutes / 100.0, + CAngleUnit::sexagesimalDegMin()) {} /*! * \brief Virtual destructor @@ -58,7 +70,7 @@ public: */ double piFactor() const { - return BlackMisc::Math::CMath::round(this->convertedSiValueToDouble() / BlackMisc::Math::CMath::PI() , 6); + return BlackMisc::Math::CMath::round(this->value(CAngleUnit::rad()) / BlackMisc::Math::CMath::PI() , 6); } /*! diff --git a/src/blackmisc/pqbase.cpp b/src/blackmisc/pqbase.cpp index 47a916f98..982ddaf0e 100644 --- a/src/blackmisc/pqbase.cpp +++ b/src/blackmisc/pqbase.cpp @@ -14,14 +14,14 @@ namespace PhysicalQuantities { // ----------------------------------------------------------------------- -// --- Mulitplier -------------------------------------------------------- +// --- Prefix ------------------------------------------------------------ // ----------------------------------------------------------------------- /* * Constructor */ -CMeasurementPrefix::CMeasurementPrefix(const QString &name, const QString &unitName, double factor) : - m_name(name), m_prefix(unitName), m_factor(factor) +CMeasurementPrefix::CMeasurementPrefix(const QString &name, const QString &symbol, double factor) : + m_name(name), m_symbol(symbol), m_factor(factor) { } @@ -29,7 +29,7 @@ CMeasurementPrefix::CMeasurementPrefix(const QString &name, const QString &unitN * Constructor */ CMeasurementPrefix::CMeasurementPrefix(const CMeasurementPrefix &other) : - m_name(other.m_name), m_prefix(other.m_prefix), m_factor(other.m_factor) + m_name(other.m_name), m_symbol(other.m_symbol), m_factor(other.m_factor) { } @@ -40,7 +40,7 @@ CMeasurementPrefix &CMeasurementPrefix::operator=(const CMeasurementPrefix &othe { if (this == &other) return *this; this->m_name = other.m_name; - this->m_prefix = other.m_prefix; + this->m_symbol= other.m_symbol; this->m_factor = other.m_factor; return *this; } @@ -62,22 +62,6 @@ bool CMeasurementPrefix::operator !=(const CMeasurementPrefix &other) const return !(*this == other); } -/* - * Greater? - */ -bool CMeasurementPrefix::operator >(const CMeasurementPrefix &other) const -{ - return this->m_factor > other.m_factor; -} - -/* - * Less? - */ -bool CMeasurementPrefix::operator <(const CMeasurementPrefix &other) const -{ - return this->m_factor < other.m_factor; -} - // ----------------------------------------------------------------------- // --- Measurement unit -------------------------------------------------- // ----------------------------------------------------------------------- @@ -85,22 +69,40 @@ bool CMeasurementPrefix::operator <(const CMeasurementPrefix &other) const /* * Constructor */ -CMeasurementUnit::CMeasurementUnit(const QString &name, const QString &unitName, const QString &type, bool isSIUnit, bool isSIBaseUnit, - double conversionFactorToSI, const CMeasurementPrefix &multiplier, qint32 displayDigits, double epsilon, - UnitConverter toSiConverter, UnitConverter fromSiConverter): - m_name(name), m_unitName(unitName), m_type(type), m_isSiUnit(isSIUnit), m_isSiBaseUnit(isSIBaseUnit), - m_conversionFactorToSIConversionUnit(conversionFactorToSI), - m_epsilon(epsilon), m_displayDigits(displayDigits), m_multiplier(multiplier), m_fromSiConverter(fromSiConverter), m_toSiConverter(toSiConverter) +CMeasurementUnit::CMeasurementUnit(const QString &name, const QString &symbol, double factor, qint32 displayDigits, double epsilon) : + m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_prefix(CMeasurementPrefix::One()), m_converter(new LinearConverter(factor)) +{ +} + +/* + * Constructor + */ +CMeasurementUnit::CMeasurementUnit(const QString &name, const QString &symbol, double factor, double offset, qint32 displayDigits, double epsilon) : + m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_prefix(CMeasurementPrefix::One()), m_converter(new AffineConverter(factor, offset)) +{ +} + +/* + * Constructor + */ +CMeasurementUnit::CMeasurementUnit(const QString &name, const QString &symbol, Converter *converter, qint32 displayDigits, double epsilon) : + m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_prefix(CMeasurementPrefix::One()), m_converter(converter) +{ +} + +/* + * Constructor + */ +CMeasurementUnit::CMeasurementUnit(const CMeasurementUnit &base, const CMeasurementPrefix &prefix, qint32 displayDigits, double epsilon) : + m_name(base.m_name), m_symbol(base.m_symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_prefix(prefix), m_converter(base.m_converter->clone(prefix)) { } /* * Copy constructor */ -CMeasurementUnit::CMeasurementUnit(const CMeasurementUnit &other): - m_name(other.m_name), m_unitName(other.m_unitName), m_type(other.m_type), m_isSiUnit(other.m_isSiUnit), - m_isSiBaseUnit(other.m_isSiBaseUnit), m_conversionFactorToSIConversionUnit(other.m_conversionFactorToSIConversionUnit), - m_epsilon(other.m_epsilon), m_displayDigits(other.m_displayDigits), m_multiplier(other.m_multiplier), m_fromSiConverter(other.m_fromSiConverter), m_toSiConverter(other.m_toSiConverter) +CMeasurementUnit::CMeasurementUnit(const CMeasurementUnit &other) : + m_name(other.m_name), m_symbol(other.m_symbol), m_epsilon(other.m_epsilon), m_displayDigits(other.m_displayDigits), m_prefix(other.m_prefix), m_converter(other.m_converter) { } @@ -111,16 +113,11 @@ CMeasurementUnit &CMeasurementUnit::operator =(const CMeasurementUnit &other) { if (this == &other) return *this; // Same object? Yes, so skip assignment, and just return *this this->m_name = other.m_name; - this->m_unitName = other.m_unitName; - this->m_type = other.m_type; - this->m_isSiUnit = other.m_isSiUnit; - this->m_isSiBaseUnit = other.m_isSiBaseUnit; - this->m_conversionFactorToSIConversionUnit = other.m_conversionFactorToSIConversionUnit; - this->m_multiplier = other.m_multiplier; + this->m_symbol = other.m_symbol; + this->m_prefix = other.m_prefix; this->m_displayDigits = other.m_displayDigits; this->m_epsilon = other.m_epsilon; - this->m_fromSiConverter = other.m_fromSiConverter; - this->m_toSiConverter = other.m_toSiConverter; + this->m_converter = other.m_converter; return *this; } @@ -130,9 +127,7 @@ CMeasurementUnit &CMeasurementUnit::operator =(const CMeasurementUnit &other) bool CMeasurementUnit::operator ==(const CMeasurementUnit &other) const { if (this == &other) return true; - if (this->m_type != other.m_type) return false; - return this->m_multiplier == other.m_multiplier && this->m_name == other.m_name - && this->m_isSiUnit == other.m_isSiUnit; + return this->m_prefix == other.m_prefix && this->m_name == other.m_name; } /* @@ -144,28 +139,29 @@ bool CMeasurementUnit::operator !=(const CMeasurementUnit &other) const } /* - * Conversion factor from unit x to y + * Conversion */ -double CMeasurementUnit::conversionToUnit(double value, const CMeasurementUnit &to) const +double CMeasurementUnit::convertFrom(double value, const CMeasurementUnit &unit) const { - if (to == *this) return value; - double siValue = this->convertToSiConversionUnit(value); - return to.convertFromSiConversionUnit(siValue); + Q_ASSERT(this->m_converter); + Q_ASSERT(unit.m_converter); + if (this->m_converter == unit.m_converter) return value; + return this->m_converter->fromDefault(unit.m_converter->toDefault(value)); } /* * Value to QString with unit, e.g. "5.00m" * @return */ -QString CMeasurementUnit::valueRoundedWithUnit(double value, int digits, bool i18n) const +QString CMeasurementUnit::makeRoundedQStringWithUnit(double value, int digits, bool i18n) const { - return this->toQStringRounded(value, digits).append(this->getUnitName(i18n)); + return this->makeRoundedQString(value, digits).append(this->getSymbol(i18n)); } /* * Value rounded */ -double CMeasurementUnit::valueRounded(double value, int digits) const +double CMeasurementUnit::roundValue(double value, int digits) const { if (digits < 0) digits = this->m_displayDigits; return CMath::round(value, digits); @@ -174,7 +170,7 @@ double CMeasurementUnit::valueRounded(double value, int digits) const /* * Rounded to QString */ -QString CMeasurementUnit::toQStringRounded(double value, int digits, bool /* i18n */) const +QString CMeasurementUnit::makeRoundedQString(double value, int digits, bool /* i18n */) const { if (digits < 0) digits = this->m_displayDigits; double v = CMath::round(value, digits); @@ -182,17 +178,5 @@ QString CMeasurementUnit::toQStringRounded(double value, int digits, bool /* i18 return s; } -/* - * Epsilon rounding - */ -double CMeasurementUnit::epsilonUpRounding(double value) const -{ - // Rounds a little up in order to avoid fractions - double eps = value > 0 ? this->m_epsilon : -1.0 * this->m_epsilon; - double v = floor((value + eps) / this->m_epsilon); - v *= this->m_epsilon; - return v; -} - } // namespace } // namespace diff --git a/src/blackmisc/pqbase.h b/src/blackmisc/pqbase.h index 78c663189..4bee55a0a 100644 --- a/src/blackmisc/pqbase.h +++ b/src/blackmisc/pqbase.h @@ -8,12 +8,14 @@ #include "blackmisc/basestreamstringifier.h" #include "blackmisc/debug.h" +#include "blackmisc/mathematics.h" #include #include #include #include #include - +#include +#include namespace BlackMisc { @@ -23,13 +25,13 @@ namespace PhysicalQuantities /*! * \brief Typical prefixes (multipliers) such as kilo, mega, hecto. * See here for an overview. - * Use the static values such CMeasurementMultiplier::k() as to specify values. + * Use the static values such as CMeasurementPrefix::k() to specify values. */ class CMeasurementPrefix : public CBaseStreamStringifier { private: QString m_name; //!< name, e.g. "kilo" - QString m_prefix; //!< prefix, e.g. "k" for kilo + QString m_symbol; //!< prefix, e.g. "k" for kilo double m_factor; //!< factor, e.g. 1000 for kilo 1/100 for centi /*! @@ -39,11 +41,11 @@ private: * \param prefixName * \param factor */ - CMeasurementPrefix(const QString &name, const QString &prefixName, double factor); + CMeasurementPrefix(const QString &name, const QString &symbol, double factor); protected: /*! - * \brief Name as stringification + * \brief Name as string * \param i18n * \return */ @@ -100,20 +102,6 @@ public: */ bool operator != (const CMeasurementPrefix &other) const; - /*! - * \brief Greater operator > - * \param other - * \return - */ - bool operator > (const CMeasurementPrefix &other) const; - - /*! - * \brief Less operator < - * \param other - * \return - */ - bool operator < (const CMeasurementPrefix &other) const; - /*! * \brief Factor, e.g.1000 for "kilo" * \return @@ -136,26 +124,18 @@ public: * \brief Name, e.g. "kilo" * \return */ - QString getName() const + QString getName(bool i18n = false) const { - return this->m_name; + return i18n ? QCoreApplication::translate("CMeasurementPrefix", this->m_name.toStdString().c_str()) : this->m_name; } /*! * \brief Prefix, e.g. "k" for "kilo" * \return */ - QString getPrefix() const + QString getSymbol(bool i18n = false) const { - return this->m_prefix; - } - - /*! - * \brief Operator as double - */ - operator double() const - { - return this->m_factor; + return i18n ? QCoreApplication::translate("CMeasurementPrefix", this->m_symbol.toStdString().c_str()) : this->m_symbol; } // --- static units, always use these for initialization @@ -178,7 +158,7 @@ public: */ static const CMeasurementPrefix &One() { - static CMeasurementPrefix one("one", "", 1.0); + static CMeasurementPrefix one(QT_TR_NOOP("one"), "", 1.0); return one; } @@ -188,7 +168,7 @@ public: */ static const CMeasurementPrefix &M() { - static CMeasurementPrefix mega("mega", "M", 1E6); + static CMeasurementPrefix mega(QT_TR_NOOP("mega"), "M", 1E6); return mega; } @@ -198,7 +178,7 @@ public: */ static const CMeasurementPrefix &k() { - static CMeasurementPrefix kilo("kilo", "k", 1000.0); + static CMeasurementPrefix kilo(QT_TR_NOOP("kilo"), "k", 1000.0); return kilo; } @@ -208,7 +188,7 @@ public: */ static const CMeasurementPrefix &G() { - static CMeasurementPrefix giga("giga", "G", 1E9); + static CMeasurementPrefix giga(QT_TR_NOOP("giga"), "G", 1E9); return giga; } @@ -218,7 +198,7 @@ public: */ static const CMeasurementPrefix &h() { - static CMeasurementPrefix hecto("hecto", "h", 100.0); + static CMeasurementPrefix hecto(QT_TR_NOOP("hecto"), "h", 100.0); return hecto; } @@ -228,7 +208,7 @@ public: */ static const CMeasurementPrefix &c() { - static CMeasurementPrefix centi("centi", "c", 0.01); + static CMeasurementPrefix centi(QT_TR_NOOP("centi"), "c", 0.01); return centi; } @@ -238,7 +218,7 @@ public: */ static const CMeasurementPrefix &m() { - static CMeasurementPrefix milli("milli", "m", 1E-03); + static CMeasurementPrefix milli(QT_TR_NOOP("milli"), "m", 1E-03); return milli; } @@ -287,46 +267,171 @@ public: /*! * \brief Base class for all units, such as meter, hertz. */ -class CMeasurementUnit: public CBaseStreamStringifier +class CMeasurementUnit : public CBaseStreamStringifier { protected: /*! - * \brief Points to an individual converter method - * Conversion as perobject, as required for CAnglewith sexagesimal conversion + * Abstract strategy pattern that encapsulates a unit conversion strategy. */ - typedef double(*UnitConverter)(const CMeasurementUnit &, double); + class Converter : public QSharedData + { + public: + /*! + * Virtual destructor. + */ + virtual ~Converter() {} + /*! + * Convert from this unit to default unit. + * \param factor + * \return + */ + virtual double toDefault(double factor) const = 0; + /*! + * Convert from default unit to this unit. + * \param factor + * \return + */ + virtual double fromDefault(double factor) const = 0; + /*! + * Make a copy of this object with a different prefix. + * \param prefix + * \return + */ + virtual Converter *clone(const CMeasurementPrefix &prefix) const = 0; + }; + + /*! + * Concrete strategy pattern for converting unit with linear conversion. + */ + class LinearConverter : public Converter + { + double m_factor; + public: + /*! + * Constructor + * \param factor + */ + LinearConverter(double factor) : m_factor(factor) {} + virtual double toDefault(double factor) const { return factor * m_factor; } + virtual double fromDefault(double factor) const { return factor / m_factor; } + virtual Converter *clone(const CMeasurementPrefix &prefix) const { auto ret = new LinearConverter(*this); ret->m_factor *= prefix.getFactor(); return ret; } + }; + + /*! + * Concrete strategy pattern for converting unit with affine conversion. + */ + class AffineConverter : public Converter + { + double m_factor; + double m_offset; + public: + /*! + * Constructor + * \param factor + * \param offset + */ + AffineConverter(double factor, double offset) : m_factor(factor), m_offset(offset) {} + virtual double toDefault(double factor) const { return (factor - m_offset) * m_factor; } + virtual double fromDefault(double factor) const { return factor / m_factor + m_offset; } + virtual Converter *clone(const CMeasurementPrefix &prefix) const { auto ret = new AffineConverter(*this); ret->m_factor *= prefix.getFactor(); return ret; } + }; + + /*! + * Concrete strategy pattern for converting unit with subdivision conversion. + */ + template + class SubdivisionConverter : public Converter + { + double m_factor; + public: + /*! + * Constructor + */ + SubdivisionConverter(double factor = 1) : m_factor(factor) {} + virtual double toDefault(double factor) const { using BlackMisc::Math::CMath; + double ret = CMath::trunc(factor); factor = CMath::fract(factor) * Den; + ret += factor / Num; + return ret * m_factor; } + virtual double fromDefault(double factor) const { using BlackMisc::Math::CMath; + factor /= m_factor; + double ret = CMath::trunc(factor); factor = CMath::fract(factor) * Num; + return ret += factor / Den; } + virtual Converter *clone(const CMeasurementPrefix &) const { qFatal("Not implemented"); return 0; } + }; + + /*! + * Concrete strategy pattern for converting unit with subdivision conversion. + */ + template + class SubdivisionConverter2 : public Converter + { + double m_factor; + public: + /*! + * Constructor + */ + SubdivisionConverter2(double factor = 1) : m_factor(factor) {} + virtual double toDefault(double factor) const { using BlackMisc::Math::CMath; + double ret = CMath::trunc(factor); factor = CMath::fract(factor) * Den1; + ret += CMath::trunc(factor) / Num1; factor = CMath::fract(factor) * Den2; + ret += factor / (Num1 * Num2); + return ret * m_factor; } + virtual double fromDefault(double factor) const { using BlackMisc::Math::CMath; + factor /= m_factor; + double ret = CMath::trunc(factor); factor = CMath::fract(factor) * Num1; + ret += CMath::trunc(factor) / Den1; factor = CMath::fract(factor) * Num2; + return ret += factor / (Den1 * Den2); } + virtual Converter *clone(const CMeasurementPrefix &) const { qFatal("Not implemented"); return 0; } + }; private: QString m_name; //!< name, e.g. "meter" - QString m_unitName; //!< unit name, e.g. "m" - QString m_type; //!< type,such as distance. Somehow redundant, but simplifies unit comparisons - bool m_isSiUnit; //!< is this a SI unit? - 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) + QString m_symbol; //!< unit name, e.g. "m" double m_epsilon; //!< values with differences below epsilon are the equal int m_displayDigits; //!< standard rounding for string conversions - CMeasurementPrefix m_multiplier; //!< multiplier (kilo, Mega) - UnitConverter m_fromSiConverter; //! allows an arbitrary conversion method as per object (e.g. angle, sexagesimal) - UnitConverter m_toSiConverter; //! allows an arbitrary conversion method as per object (e.g. angle, sexagesimal) + CMeasurementPrefix m_prefix; //!< multiplier (kilo, Mega) + QSharedDataPointer m_converter; //!< strategy pattern allows an arbitrary conversion method as per object protected: /*! - * Constructor by parameter + * Construct a unit with linear conversion * \param name - * \param unitName - * \param type - * \param isSiUnit - * \param isSiBaseUnit - * \param conversionFactorToSI - * \param multiplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon - * \param toSiConverter - * \param fromSiConverter */ - CMeasurementUnit(const QString &name, const QString &unitName, const QString &type, bool isSiUnit, bool isSiBaseUnit, double conversionFactorToSI = 1, - const CMeasurementPrefix &multiplier = CMeasurementPrefix::None(), qint32 displayDigits = 2, - double epsilon = 1E-10, UnitConverter toSiConverter = 0, UnitConverter fromSiConverter = 0); + CMeasurementUnit(const QString &name, const QString &symbol, double factor, int displayDigits, double epsilon); + + /*! + * Construct a unit with affine conversion + * \param name + * \param symbol + * \param factor + * \param offset + * \param displayDigits + * \param epsilon + */ + CMeasurementUnit(const QString &name, const QString &symbol, double factor, double offset, int displayDigits, double epsilon); + + /*! + * Construct a unit with custom conversion + * \param name + * \param symbol + * \param converter + * \param displayDigits + * \param epsilon + */ + CMeasurementUnit(const QString &name, const QString &symbol, Converter *converter, int displayDigits, double epsilon); + + /*! + * Construct from base unit and prefix + * \param base + * \param prefix + * \param displayDigits + * \param epsilon + */ + CMeasurementUnit(const CMeasurementUnit &base, const CMeasurementPrefix &prefix, int displayDigits = 2, double epsilon = 1E-10); /*! * \brief Copy constructor @@ -357,38 +462,7 @@ protected: */ virtual QString convertToQString(bool i18n = false) const { - return this->getUnitName(i18n); - } - - /*! - * \brief Conversion factor to SI conversion unit - * \return - */ - double getConversionFactorToSI() const - { - return this->m_conversionFactorToSIConversionUnit; - } - - /*! - * Given value to conversion SI conversion unit (e.g. meter, hertz). - * Standard implementaion is simply factor based. - * \param value - * \return - */ - virtual double conversionToSiConversionUnit(double value) const - { - return value * this->m_conversionFactorToSIConversionUnit; - } - - /*! - * \brief Value from SI conversion unit to this unit. - * Standard implementation is simply factor based. - * \param value - * \return - */ - virtual double conversionFromSiConversionUnit(double value) const - { - return value / this->m_conversionFactorToSIConversionUnit; + return this->getSymbol(i18n); } /*! @@ -397,7 +471,7 @@ protected: */ virtual void marshallToDbus(QDBusArgument &argument) const { - argument << this->m_unitName; + argument << this->m_symbol; } /*! @@ -411,6 +485,22 @@ protected: (*this) = CMeasurementUnit::None(); } + /*! + * \brief Unit from symbol + * \param symbol must be a valid unit symbol (without i18n) or empty string (empty means default unit) + * \return + */ + template static const U &unitFromSymbol(const QString &symbol) + { + if (symbol.isEmpty()) return U::defaultUnit(); + const QList &units = U::allUnits(); + for (int i = 0; i < units.size(); ++i) { + if (units.at(i).getSymbol() == symbol) return units.at(i); + } + qFatal("Illegal unit name"); + return U::defaultUnit(); // just suppress "not all control paths return a value" + } + public: /*! * \brief Equal operator == @@ -426,33 +516,6 @@ public: */ bool operator != (const CMeasurementUnit &other) const; - /*! - * \brief Representing an SI unit? Examples: kilometer, meter, hertz - * \return - */ - bool isSiUnit() const - { - return this->m_isSiUnit; - } - - /*! - * \brief Representing an base SI unit? Examples: second, meter - * \return - */ - bool isSiBaseUnit() const - { - return this->m_isSiUnit; - } - - /*! - * \brief Representing an SI base unit? Example: meter - * \return - */ - bool isUnprefixedSiUnit() const - { - return this->m_isSiUnit && this->m_multiplier.getFactor() == 1; - } - /*! * \brief Name such as "meter" * \param i18n @@ -460,7 +523,8 @@ public: */ QString getName(bool i18n = false) const { - return i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_name.toStdString().c_str()) : this->m_name; + QString base = i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_name.toStdString().c_str()) : this->m_name; + return this->m_prefix.getName(i18n) + base; } /*! @@ -468,41 +532,19 @@ public: * \param i18n * \return */ - QString getUnitName(bool i18n = false) const + QString getSymbol(bool i18n = false) const { - return i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_unitName.toStdString().c_str()) : this->m_unitName; + QString base = i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_symbol.toStdString().c_str()) : this->m_symbol; + return this->m_prefix.getSymbol(i18n) + base; } /*! - * \brief Type such as "distance", "frequency" - * \return - */ - QString getType() const - { - return this->m_type; - } - - /*! - * Given value to conversion SI conversion unit (e.g. meter, hertz). - * Standard implementation is simply factor based. + * \brief Rounded value * \param value + * \param digits * \return */ - double convertToSiConversionUnit(double value) const - { - return (this->m_toSiConverter) ? this->m_toSiConverter((*this), value) : this->conversionToSiConversionUnit(value); - } - - /*! - * Value from SI conversion unit to this unit. - * Standard implementation is simply factor based. - * \param value - * \return - */ - double convertFromSiConversionUnit(double value) const - { - return (this->m_fromSiConverter) ? this->m_fromSiConverter((*this), value) : this->conversionFromSiConversionUnit(value); - } + double roundValue(double value, int digits = -1) const; /*! * Rounded string utility method, virtual so units can have @@ -512,15 +554,7 @@ public: * \param i18n * \return */ - virtual QString toQStringRounded(double value, int digits = -1, bool i18n = false) const; - - /*! - * \brief Rounded value - * \param value - * \param digits - * \return - */ - double valueRounded(double value, int digits = -1) const; + virtual QString makeRoundedQString(double value, int digits = -1, bool i18n = false) const; /*! * \brief Value rounded with unit, e.g. "5.00m", "30kHz" @@ -529,7 +563,7 @@ public: * \param i18n * \return */ - virtual QString valueRoundedWithUnit(double value, int digits = -1, bool i18n = false) const; + virtual QString makeRoundedQStringWithUnit(double value, int digits = -1, bool i18n = false) const; /*! * \brief Threshold for rounding @@ -544,7 +578,7 @@ public: * \brief getDisplayDigits * \return */ - qint32 getDisplayDigits() const + int getDisplayDigits() const { return this->m_displayDigits; } @@ -553,26 +587,16 @@ public: * \brief Multiplier such as "kilo" * \return */ - CMeasurementPrefix getMultiplier() const + CMeasurementPrefix getPrefix() const { - return this->m_multiplier; + return this->m_prefix; } /*! - * \brief Factor to convert to given unit - * \param value - * \param to - * \return + * Convert from other unit to this unit. + * \param */ - double conversionToUnit(double value, const CMeasurementUnit &to) const; - - /*! - * Epsilon rounding. In some conversion rouding is required to avoid - * periodical numbers. - * \param value - * \return - */ - double epsilonUpRounding(double value) const; + double convertFrom(double value, const CMeasurementUnit &unit) const; /*! * \brief Is given value <= epsilon? @@ -595,7 +619,7 @@ public: */ static CMeasurementUnit &None() { - static CMeasurementUnit none("none", "", "", false, false, 0.0, CMeasurementPrefix::None(), 0, 0); + static CMeasurementUnit none("none", "", 0.0, 0, 0); return none; } }; diff --git a/src/blackmisc/pqconstants.h b/src/blackmisc/pqconstants.h index d2a7ce937..fa67d9a4e 100644 --- a/src/blackmisc/pqconstants.h +++ b/src/blackmisc/pqconstants.h @@ -69,6 +69,16 @@ public: return p; } + /*! + * \brief Standard pressure datum for flight levels expressed in mmHg, such as in Russia, 760mmHg + * \return + */ + static const CPressure& RuFlightLevelPressure() + { + static CPressure p(760, CPressureUnit::mmHg()); + return p; + } + /*! * \brief Unicom frequency * \return diff --git a/src/blackmisc/pqfrequency.h b/src/blackmisc/pqfrequency.h index 7d106204a..96b790d95 100644 --- a/src/blackmisc/pqfrequency.h +++ b/src/blackmisc/pqfrequency.h @@ -22,7 +22,7 @@ public: /*! * \brief Default constructor */ - CFrequency() : CPhysicalQuantity(0, CFrequencyUnit::Hz(), CFrequencyUnit::Hz()) {} + CFrequency() : CPhysicalQuantity(0, CFrequencyUnit::defaultUnit()) {} /** *\brief Copy constructor from base type @@ -34,7 +34,7 @@ public: * \param value * \param unit */ - CFrequency(double value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit, CFrequencyUnit::Hz()) {} + CFrequency(double value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Virtual destructor diff --git a/src/blackmisc/pqlength.h b/src/blackmisc/pqlength.h index fe24480b0..559b7f172 100644 --- a/src/blackmisc/pqlength.h +++ b/src/blackmisc/pqlength.h @@ -22,7 +22,7 @@ public: /*! * \brief Default constructor */ - CLength() : CPhysicalQuantity(0, CLengthUnit::m(), CLengthUnit::m()) {} + CLength() : CPhysicalQuantity(0, CLengthUnit::defaultUnit()) {} /** *\brief Copy constructor from base type @@ -34,7 +34,7 @@ public: * \param value * \param unit */ - CLength(double value, const CLengthUnit &unit) : CPhysicalQuantity(value, unit, CLengthUnit::m()) {} + CLength(double value, const CLengthUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Virtual destructor diff --git a/src/blackmisc/pqmass.h b/src/blackmisc/pqmass.h index 266b54929..9b949b78b 100644 --- a/src/blackmisc/pqmass.h +++ b/src/blackmisc/pqmass.h @@ -21,14 +21,14 @@ public: /*! * \brief Default constructor */ - CMass() : CPhysicalQuantity(0, CMassUnit::kg(), CMassUnit::kg()) {} + CMass() : CPhysicalQuantity(0, CMassUnit::defaultUnit()) {} /*! * \brief Init by double value * \param value * \param unit */ - CMass(double value, const CMassUnit &unit) : CPhysicalQuantity(value, unit, CMassUnit::kg()) {} + CMass(double value, const CMassUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Copy constructor from base type diff --git a/src/blackmisc/pqphysicalquantity.cpp b/src/blackmisc/pqphysicalquantity.cpp index 63b7ba8b3..945c0aa68 100644 --- a/src/blackmisc/pqphysicalquantity.cpp +++ b/src/blackmisc/pqphysicalquantity.cpp @@ -13,25 +13,16 @@ namespace PhysicalQuantities /* * Constructor by double */ -template CPhysicalQuantity::CPhysicalQuantity(double baseValue, const MU &unit, const MU &siConversionUnit) : - m_unit(unit), m_conversionSiUnit(siConversionUnit) +template CPhysicalQuantity::CPhysicalQuantity(double value, const MU &unit) : + m_value(value), m_unit(unit) { - this->setUnitValue(baseValue); } /* * Copy constructor */ template CPhysicalQuantity::CPhysicalQuantity(const CPhysicalQuantity &other) : - m_unitValueD(other.m_unitValueD), m_convertedSiUnitValueD(other.m_convertedSiUnitValueD), - m_unit(other.m_unit), m_conversionSiUnit(other.m_conversionSiUnit) -{ -} - -/* - * Destructor - */ -template CPhysicalQuantity::~CPhysicalQuantity() + m_value(other.m_value), m_unit(other.m_unit) { } @@ -41,25 +32,8 @@ template CPhysicalQuantity::~CPhysicalQuantity() template bool CPhysicalQuantity::operator ==(const CPhysicalQuantity &other) const { if (this == &other) return true; - if (this->m_unit.getType() != other.m_unit.getType()) return false; - - // some special cases for best quality - double diff; - const double lenient = 1.001; // even diff already has a rounding issue to be avoided - bool eq = false; - if (this->m_unit == other.m_unit) - { - // same unit, comparison based on double - diff = qAbs(this->m_unitValueD - other.m_unitValueD); - eq = diff <= (lenient * this->m_unit.getEpsilon()); - } - else - { - // based on SI value - diff = qAbs(this->m_convertedSiUnitValueD - other.m_convertedSiUnitValueD); - eq = diff <= (lenient * this->m_conversionSiUnit.getEpsilon()); - } - return eq; + double diff = abs(this->m_value - other.value(this->m_unit)); + return diff <= this->m_unit.getEpsilon(); } /* @@ -77,10 +51,8 @@ template CPhysicalQuantity& CPhysicalQuantitym_unitValueD = other.m_unitValueD; - this->m_convertedSiUnitValueD = other.m_convertedSiUnitValueD; + this->m_value = other.m_value; this->m_unit = other.m_unit; - this->m_conversionSiUnit = other.m_conversionSiUnit; return *this; } @@ -89,15 +61,7 @@ template CPhysicalQuantity& CPhysicalQuantity CPhysicalQuantity &CPhysicalQuantity::operator +=(const CPhysicalQuantity &other) { - if (this->m_unit == other.m_unit) - { - this->setUnitValue(other.m_unitValueD + this->m_unitValueD); - } - else - { - double v = other.value(this->m_unit); - this->setUnitValue(v + this->m_unitValueD); - } + this->m_value += other.value(this->m_unit); return *this; } @@ -114,17 +78,17 @@ template PQ CPhysicalQuantity::operator +(const PQ /* * Explicit plus */ -template void CPhysicalQuantity::addUnitValue(double value) +template void CPhysicalQuantity::addValueSameUnit(double value) { - this->setUnitValue(this->m_unitValueD + value); + this->m_value += value; } /* * Explicit minus */ -template void CPhysicalQuantity::substractUnitValue(double value) +template void CPhysicalQuantity::substractValueSameUnit(double value) { - this->setUnitValue(this->m_unitValueD - value); + this->m_value -= value; } /* @@ -132,15 +96,7 @@ template void CPhysicalQuantity::substractUnitValue */ template CPhysicalQuantity &CPhysicalQuantity::operator -=(const CPhysicalQuantity &other) { - if (this->m_unit == other.m_unit) - { - this->setUnitValue(other.m_unitValueD - this->m_unitValueD); - } - else - { - double v = other.value(this->m_unit); - this->setUnitValue(v - this->m_unitValueD); - } + this->m_value -= other.value(this->m_unit); return *this; } @@ -157,38 +113,38 @@ template PQ CPhysicalQuantity::operator -(const PQ /* * Multiply operator */ -template CPhysicalQuantity &CPhysicalQuantity::operator *=(double multiply) +template CPhysicalQuantity &CPhysicalQuantity::operator *=(double factor) { - this->setUnitValue(this->m_unitValueD * multiply); + this->m_value *= factor; return *this; } /* * Multiply operator */ -template PQ CPhysicalQuantity::operator *(double multiply) const +template PQ CPhysicalQuantity::operator *(double factor) const { PQ copy = *derived(); - copy *= multiply; + copy *= factor; return copy; } /* * Divide operator /= */ -template CPhysicalQuantity &CPhysicalQuantity::operator /=(double divide) +template CPhysicalQuantity &CPhysicalQuantity::operator /=(double divisor) { - this->setUnitValue(this->m_unitValueD / divide); + this->m_value /= divisor; return *this; } /* * Divide operator / */ -template PQ CPhysicalQuantity::operator /(double divide) const +template PQ CPhysicalQuantity::operator /(double divisor) const { PQ copy = *derived(); - copy /= divide; + copy /= divisor; return copy; } @@ -199,9 +155,7 @@ template bool CPhysicalQuantity::operator <(const C { if ((*this) == other) return false; - // == considers epsilon, so we now have a diff > epsilon here - double diff = this->m_convertedSiUnitValueD - other.m_convertedSiUnitValueD; - return (diff < 0); + return (this->m_value < other.value(this->m_unit)); } /* @@ -238,9 +192,8 @@ template PQ &CPhysicalQuantity::switchUnit(const MU { if (this->m_unit != newUnit) { - double cf = this->m_unit.conversionToUnit(this->m_unitValueD, newUnit); + this->m_value = newUnit.convertFrom(this->m_value, this->m_unit); this->m_unit = newUnit; - this->setUnitValue(cf); } return *derived(); } @@ -248,60 +201,9 @@ template PQ &CPhysicalQuantity::switchUnit(const MU /* * Init by double */ -template void CPhysicalQuantity::setUnitValue(double baseValue) +template void CPhysicalQuantity::setValueSameUnit(double baseValue) { - this->m_unitValueD = baseValue; - this->setConversionSiUnitValue(); -} - -/* - * Set SI value - */ -template void CPhysicalQuantity::setConversionSiUnitValue() -{ - double si = this->m_unit.convertToSiConversionUnit(this->m_unitValueD); - this->m_convertedSiUnitValueD = si; -} - -/* - * Round - */ -template double CPhysicalQuantity::unitValueToDoubleRounded(int digits) const -{ - return this->m_unit.valueRounded(this->m_unitValueD, digits); -} - -/* - * Rounded value to QString - */ -template QString CPhysicalQuantity::unitValueToQStringRounded(int digits) const -{ - return this->m_unit.toQStringRounded(this->m_unitValueD, digits); -} - -/* - * Rounded with unit - */ -template QString CPhysicalQuantity::unitValueRoundedWithUnit(int digits, bool i18n) const -{ - return this->m_unit.valueRoundedWithUnit(this->m_unitValueD, digits, i18n); -} - -/* - * Rounded SI value to QString - */ -template QString CPhysicalQuantity::convertedSiValueToQStringRounded(int digits) const -{ - if (digits < 1) digits = this->m_conversionSiUnit.getDisplayDigits(); - return this->m_conversionSiUnit.toQStringRounded(this->m_convertedSiUnitValueD, digits); -} - -/* - * SI base unit value with unit - */ -template QString CPhysicalQuantity::convertedSiValueRoundedWithUnit(int digits, bool i18n) const -{ - return this->m_conversionSiUnit.valueRoundedWithUnit(this->m_convertedSiUnitValueD, digits, i18n); + this->m_value = baseValue; } /* @@ -309,9 +211,7 @@ template QString CPhysicalQuantity::convertedSiValu */ template QString CPhysicalQuantity::valueRoundedWithUnit(const MU &unit, int digits, bool i18n) const { - if (unit == this->m_unit) return this->unitValueRoundedWithUnit(digits, i18n); - if (unit == this->m_conversionSiUnit) return this->convertedSiValueRoundedWithUnit(digits, i18n); - return unit.valueRoundedWithUnit(this->value(unit), digits, i18n); + return unit.makeRoundedQStringWithUnit(this->value(unit), digits, i18n); } /* @@ -319,7 +219,7 @@ template QString CPhysicalQuantity::valueRoundedWit */ template double CPhysicalQuantity::valueRounded(const MU &unit, int digits) const { - return unit.valueRounded(this->value(unit), digits); + return unit.roundValue(this->value(unit), digits); } /* @@ -327,19 +227,7 @@ template double CPhysicalQuantity::valueRounded(con */ template double CPhysicalQuantity::value(const MU &unit) const { - if (unit == this->m_unit) return this->m_unitValueD; - if (unit == this->m_conversionSiUnit) return this->m_convertedSiUnitValueD; - double v = unit.convertFromSiConversionUnit(this->m_convertedSiUnitValueD); - return v; -} - -/* - * Round utility method - */ -template double CPhysicalQuantity::convertedSiValueToDoubleRounded(int digits) const -{ - if (digits < 1) digits = this->m_conversionSiUnit.getDisplayDigits(); - return this->m_conversionSiUnit.valueRounded(this->m_convertedSiUnitValueD, digits); + return unit.convertFrom(this->m_value, this->m_unit); } // see here for the reason of thess forward instantiations diff --git a/src/blackmisc/pqphysicalquantity.h b/src/blackmisc/pqphysicalquantity.h index 586755265..20ac9b10f 100644 --- a/src/blackmisc/pqphysicalquantity.h +++ b/src/blackmisc/pqphysicalquantity.h @@ -27,8 +27,13 @@ namespace PhysicalQuantities template class CPhysicalQuantity : public BlackMisc::CBaseStreamStringifier { private: - double m_unitValueD; //!< value backed by double - double m_convertedSiUnitValueD; //!< SI unit value + double m_value; //!< numeric part + MU m_unit; //!< unit part + + /*! + * Which subclass of CMeasurementUnit does this quantity use? + */ + typedef MU UnitClass; /*! * \brief Easy access to derived class (CRTP template parameter) @@ -49,16 +54,25 @@ private: } protected: - MU m_unit; //!< unit - MU m_conversionSiUnit; //!< corresponding SI base unit - /*! * \brief Constructor with double - * \param baseValue + * \param value * \param unit - * \param siConversionUnit */ - CPhysicalQuantity(double baseValue, const MU &unit, const MU &siConversionUnit); + CPhysicalQuantity(double value, const MU &unit); + + /*! + * \brief Copy constructor + * \param other + */ + CPhysicalQuantity(const CPhysicalQuantity &other); + + /*! + * \brief Assignment operator = + * \param other + * \return + */ + CPhysicalQuantity &operator =(const CPhysicalQuantity &other); /*! * \brief Name as string @@ -67,32 +81,20 @@ protected: */ virtual QString convertToQString(bool i18n = false) const { - return this->unitValueRoundedWithUnit(-1, i18n); + return this->valueRoundedWithUnit(this->getUnit(), -1, i18n); } /*! - * \brief Init by double - * \param baseValue + * \brief Change value without changing unit + * \param value */ - - void setUnitValue(double baseValue); - - /*! - * \brief Set the SI value - */ - void setConversionSiUnitValue(); + void setValueSameUnit(double value); public: - /*! - * \brief Copy constructor - * \param other - */ - CPhysicalQuantity(const CPhysicalQuantity &other); - /*! * \brief Virtual destructor */ - virtual ~CPhysicalQuantity(); + virtual ~CPhysicalQuantity() {} /*! * \brief Unit of the distance @@ -104,48 +106,12 @@ public: } /*! - * \brief Conversion SI unit - * \return - */ - MU getConversionSiUnit() const - { - return this->m_conversionSiUnit; - } - - /*! - * \brief Switch unit, e.g. feet to meter + * \brief Change unit, and convert value to maintain the same quantity * \param newUnit * \return */ PQ &switchUnit(const MU &newUnit); - /*! - * \brief Value in SI base unit? Meter is an SI base unit, hertz not! - * \return - */ - bool isSiBaseUnit() const - { - return this->m_unit.isSiBaseUnit(); - } - - /*! - * \brief Value in SI unit? Hertz is an derived SI unit, NM not! - * \return - */ - bool isSiUnit() const - { - return this->m_unit.isSiUnit(); - } - - /*! - * \brief Value in unprefixed SI unit? Meter is a unprefixed, kilometer a prefixed SI Unit - * \return - */ - bool isUnprefixedSiUnit() const - { - return this->m_unit.isUnprefixedSiUnit(); - } - /*! * \brief Value in given unit * \param unit @@ -154,7 +120,16 @@ public: double value(const MU &unit) const; /*! - * \brief Rounded value in unit + * \brief Value in current unit + * \return + */ + double value() const + { + return this->m_value; + } + + /*! + * \brief Rounded value in given unit * \param unit * \param digits * \return @@ -162,7 +137,17 @@ public: double valueRounded(const MU &unit, int digits = -1) const; /*! - * \brief Value to QString with unit, e.g. "5.00m" + * \brief Rounded value in current unit + * \param digits + * \return + */ + double valueRounded(int digits = -1) const + { + return this->valueRounded(this->m_unit, digits); + } + + /*! + * \brief Value to QString with the given unit, e.g. "5.00m" * \param unit * \param digits * \param i18n @@ -171,80 +156,27 @@ public: QString valueRoundedWithUnit(const MU &unit, int digits = -1, bool i18n = false) const; /*! - * \brief Value as double - * \return - */ - double unitValueToDouble() const - { - return this->m_unitValueD; - } - - /*! - * \brief Value to QString with unit, e.g. "5.00m" + * \brief Value to QString with the current unit, e.g. "5.00m" * \param digits * \param i18n * \return */ - QString unitValueRoundedWithUnit(int digits = -1, bool i18n = false) const; - - /*! - * \brief Rounded value by n digits - * \param digits - * \return - */ - double unitValueToDoubleRounded(int digits = -1) const; - - /*! - * \brief Rounded value by n digits - * \param digits if no value is provided, unit rounding is taken - * \return - */ - QString unitValueToQStringRounded(int digits = -1) const; - - /*! - * \brief Conversion SI value as double - * \return - */ - double convertedSiValueToDouble() const + QString valueRoundedWithUnit(int digits = -1, bool i18n = false) const { - return this->m_convertedSiUnitValueD; + return this->valueRoundedWithUnit(this->m_unit, digits, i18n); } /*! - * \brief Rounded SI value by n digits - * \param digits - * \return - */ - double convertedSiValueToDoubleRounded(int digits = -1) const; - - /*! - * \brief Rounded value by n digits - * \param digits if no value is provided, unit rounding is taken - * \return - */ - QString convertedSiValueToQStringRounded(int digits = -1) const; - - /*! - * \brief SI Base unit value rounded - * \param digits - * \param i18n - * \return - */ - QString convertedSiValueRoundedWithUnit(int digits = -1, bool i18n = false) const; - - /*! - * \brief Add to the unit value. - * \remarks Since overloading the + operator with double did lead to unintended conversions, as explicit method + * \brief Add to the value in the current unit. * \param value */ - void addUnitValue(double value); + void addValueSameUnit(double value); /*! - * \brief Substract to the unit value. - * \remarks Since overloading the - operator with double did lead to unintended conversions, as explicit method + * \brief Substract from the value in the current unit. * \param value */ - void substractUnitValue(double value); + void substractValueSameUnit(double value); /*! * \brief Multiply operator *= @@ -341,13 +273,6 @@ public: */ bool operator >=(const CPhysicalQuantity &other) const; - /*! - * \brief Assignment operator = - * \param other - * \return - */ - CPhysicalQuantity &operator =(const CPhysicalQuantity &other); - /*! * \brief Plus operator + * \param other @@ -368,25 +293,25 @@ public: */ bool isZeroEpsilon() const { - return this->m_unit.isEpsilon(this->m_unitValueD); + return this->m_unit.isEpsilon(this->m_value); } /*! * \brief Value >= 0 epsilon considered * \return */ - bool isGreaterOrEqualZeroEpsilon() const + bool isNonNegativeEpsilon() const { - return this->isZeroEpsilon() || this->m_unitValueD > 0; + return this->isZeroEpsilon() || this->m_value > 0; } /*! * \brief Value <= 0 epsilon considered * \return */ - bool isLessOrEqualZeroEpsilon() const + bool isNonPositiveEpsilon() const { - return this->isZeroEpsilon() || this->m_unitValueD < 0; + return this->isZeroEpsilon() || this->m_value < 0; } /*! @@ -395,10 +320,9 @@ public: */ virtual void marshallToDbus(QDBusArgument &argument) const { - argument << this->m_unitValueD; - argument << this->m_convertedSiUnitValueD; + argument << this->value(UnitClass::defaultUnit()); + argument << this->m_value; argument << this->m_unit; - argument << this->m_conversionSiUnit; } /*! @@ -407,10 +331,10 @@ public: */ virtual void unmarshallFromDbus(const QDBusArgument &argument) { - argument >> this->m_unitValueD; - argument >> this->m_convertedSiUnitValueD; + double ignore; + argument >> ignore; + argument >> this->m_value; argument >> this->m_unit; - argument >> this->m_conversionSiUnit; } /*! diff --git a/src/blackmisc/pqpressure.h b/src/blackmisc/pqpressure.h index 80d57f96c..38d08778f 100644 --- a/src/blackmisc/pqpressure.h +++ b/src/blackmisc/pqpressure.h @@ -23,7 +23,7 @@ public: /*! * \brief Default constructor */ - CPressure() : CPhysicalQuantity(0, CPressureUnit::Pa(), CPressureUnit::Pa()) {} + CPressure() : CPhysicalQuantity(0, CPressureUnit::defaultUnit()) {} /** *\brief Copy constructor from base type @@ -35,7 +35,7 @@ public: * \param value * \param unit */ - CPressure(double value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit, CPressureUnit::Pa()) {} + CPressure(double value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Virtual destructor diff --git a/src/blackmisc/pqspeed.h b/src/blackmisc/pqspeed.h index f5ecf2e72..889916f42 100644 --- a/src/blackmisc/pqspeed.h +++ b/src/blackmisc/pqspeed.h @@ -23,7 +23,7 @@ public: /*! * \brief Default constructor */ - CSpeed() : CPhysicalQuantity(0, CSpeedUnit::m_s(), CSpeedUnit::m_s()) {} + CSpeed() : CPhysicalQuantity(0, CSpeedUnit::defaultUnit()) {} /*! *\brief Copy constructor from base type @@ -35,7 +35,7 @@ public: * \param value * \param unit */ - CSpeed(double value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit, CSpeedUnit::m_s()) {} + CSpeed(double value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Destructor diff --git a/src/blackmisc/pqtemperature.h b/src/blackmisc/pqtemperature.h index 4553493fd..e8697e509 100644 --- a/src/blackmisc/pqtemperature.h +++ b/src/blackmisc/pqtemperature.h @@ -22,7 +22,7 @@ public: /*! * \brief Default constructor */ - CTemperature() : CPhysicalQuantity(0, CTemperatureUnit::K(), CTemperatureUnit::K()) {} + CTemperature() : CPhysicalQuantity(0, CTemperatureUnit::defaultUnit()) {} /** * \brief Copy constructor from base type @@ -34,7 +34,7 @@ public: * \param value * \param unit */ - CTemperature(double value, const CTemperatureUnit &unit): CPhysicalQuantity(value, unit, CTemperatureUnit::K()) {} + CTemperature(double value, const CTemperatureUnit &unit): CPhysicalQuantity(value, unit) {} /*! * \brief Destructor diff --git a/src/blackmisc/pqtime.h b/src/blackmisc/pqtime.h index 16bbf9fe4..060585c70 100644 --- a/src/blackmisc/pqtime.h +++ b/src/blackmisc/pqtime.h @@ -23,7 +23,7 @@ public: /*! * \brief Default constructor */ - CTime() : CPhysicalQuantity(0, CTimeUnit::s(), CTimeUnit::s()) {} + CTime() : CPhysicalQuantity(0, CTimeUnit::defaultUnit()) {} /** *\brief Copy constructor from base type @@ -35,7 +35,7 @@ public: * \param value * \param unit */ - CTime(double value, const CTimeUnit &unit) : CPhysicalQuantity(value, unit, CTimeUnit::s()) {} + CTime(double value, const CTimeUnit &unit) : CPhysicalQuantity(value, unit) {} /*! * \brief Destructor diff --git a/src/blackmisc/pqunits.cpp b/src/blackmisc/pqunits.cpp index 5973a3c10..f7de957aa 100644 --- a/src/blackmisc/pqunits.cpp +++ b/src/blackmisc/pqunits.cpp @@ -10,79 +10,74 @@ namespace BlackMisc namespace PhysicalQuantities { -/* - * Convert to SI - */ -double CTemperatureUnit::conversionToSiConversionUnit(double value) const -{ - double v = value + this->m_conversionOffsetToSi; - v *= this->getConversionFactorToSI(); - return v; -} +using BlackMisc::Math::CMath; /* - * Convert from SI + * Rounded to QString */ -double CTemperatureUnit::conversionFromSiConversionUnit(double value) const +QString CAngleUnit::makeRoundedQString(double value, int digits, bool i18n) const { - double v = value / this->getConversionFactorToSI(); - v -= this->m_conversionOffsetToSi; - return v; -} - -/* - * Convert from SI - */ -double CAngleUnit::conversionSexagesimalFromSi(const CMeasurementUnit &angleUnit, double value) -{ - // using rounding here, since fractions can lead to ugly sexagesimal conversion - // e.g. 185.499999 gives 185 29' 59.9999" - value = angleUnit.epsilonUpRounding(value * 180 / M_PI); // degree - double v = floor(value); - double c = value - v; - double mr = c * 60.0; - double m = floor(mr); // minutes - double s = (mr - m) * 60; // seconds + rest fraction - v = (v + (m / 100) + (s / 10000)); - return v; -} - -/* - * Convert to SI - */ -double CAngleUnit::conversionSexagesimalToSi(const CMeasurementUnit &, double value) -{ - double v = floor(value); // degrees - double c = value - v; - c = c * 100.0; - double m = floor(c); - c = c - m; - m /= 60.0; // minutes back to decimals - double s = c / 36.0; // seconds back to decimals - v = v + m + s; - return v / 180.0 * M_PI; + if (digits < 0) digits = this->getDisplayDigits(); + QString s; + if ((*this) == CAngleUnit::sexagesimalDeg()) + { + double de = CMath::trunc(value); + double mi = CMath::trunc((value - de) * 100.0); + double se = CMath::trunc((value - de - mi / 100.0) * 1000000) / 100.0; + const char *fmt = value < 0 ? "-%L1 %L2'%L3\"" : "%L1 %L2'%L3\""; + s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt; + s = s.arg(fabs(de), 0, 'f', 0).arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0'); + } + else if ((*this) == CAngleUnit::sexagesimalDegMin()) + { + double de = CMath::trunc(value); + double mi = CMath::trunc((value - de) * 100.0); + const char *fmt = value < 0 ? "-%L1 %L2'" : "%L1 %L2'"; + s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt; + s = s.arg(fabs(de), 0, 'f', 0).arg(fabs(mi), 2, 'f', digits, '0'); + } + else + { + s = this->CMeasurementUnit::makeRoundedQString(value, digits, i18n); + } + return s; } /* * Rounded to QString */ -QString CAngleUnit::toQStringRounded(double value, int digits, bool i18n) const +QString CTimeUnit::makeRoundedQString(double value, int digits, bool i18n) const { + if (digits < 0) digits = this->getDisplayDigits(); QString s; - if ((*this) == CAngleUnit::sexagesimalDeg()) + if ((*this) == CTimeUnit::hms()) { - // 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; - QString ses = QLocale::system().toString(se, 'f', 2); - s = QString::number(de); - s = s.append(i18n ? CAngleUnit::deg().getUnitName(true) : " "); - s = s.append(QString::number(mi)).append("'").append(ses).append("\""); + double hr = CMath::trunc(value); + double mi = CMath::trunc((value - hr) * 100.0); + double se = CMath::trunc((value - hr - mi / 100.0) * 1000000) / 100.0; + const char *fmt = value < 0 ? "-%L1h%L2m%L3s" : "%L1h%L2m%L3s"; + s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt; + s = s.arg(fabs(hr), 0, 'f', 0).arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0'); + } + else if ((*this) == CTimeUnit::hrmin()) + { + double hr = CMath::trunc(value); + double mi = CMath::trunc((value - hr) * 100.0); + const char *fmt = value < 0 ? "-%L1h%L2m" : "%L1h%L2m"; + s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt; + s = s.arg(fabs(hr), 0, 'f', 0).arg(fabs(mi), 2, 'f', digits, '0'); + } + else if ((*this) == CTimeUnit::minsec()) + { + double mi = CMath::trunc(value); + double se = CMath::trunc((value - mi) * 100.0); + const char *fmt = value < 0 ? "-%L2m%L3s" : "%L2m%L3s"; + s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt; + s = s.arg(fabs(mi), 0, 'f', 0).arg(fabs(se), 2, 'f', digits, '0'); } else { - s = this->CMeasurementUnit::toQStringRounded(value, digits); + s = this->CMeasurementUnit::makeRoundedQString(value, digits, i18n); } return s; } diff --git a/src/blackmisc/pqunits.h b/src/blackmisc/pqunits.h index a6c355580..b461fdda6 100644 --- a/src/blackmisc/pqunits.h +++ b/src/blackmisc/pqunits.h @@ -33,22 +33,29 @@ private: /*! * \brief Constructor length unit * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CLengthUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "distance", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CLengthUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} + + /*! + * \brief Constructor length unit + * \param prefix + * \param base + * \param displayDigits + * \param epsilon + */ + CLengthUnit(const CMeasurementPrefix &prefix, const CLengthUnit &base, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(base, prefix, displayDigits, epsilon) {} public: /*! - * Default constructor, we do not want this, but required for Qt Metasystem + * Default constructor, required for Qt Metasystem */ - CLengthUnit() : CMeasurementUnit("meter", "m", "distance", true, true) {} + CLengthUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor @@ -56,13 +63,19 @@ public: */ CLengthUnit(const CLengthUnit &other) : CMeasurementUnit(other) {} + /*! + * \brief Default unit + * \return + */ + static const CLengthUnit &defaultUnit() { return m(); } + /*! * \brief Meter m * \return */ static const CLengthUnit &m() { - static CLengthUnit m(QT_TRANSLATE_NOOP("CMeasurementUnit", "meter"), "m", true, true); + static CLengthUnit m(QT_TRANSLATE_NOOP("CMeasurementUnit", "meter"), "m", 1); return m; } @@ -72,7 +85,7 @@ public: */ static const CLengthUnit &NM() { - static CLengthUnit NM(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical mile"), "NM", false, false, 1000.0 * 1.85200, CMeasurementPrefix::One(), 3); + static CLengthUnit NM(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical mile"), "NM", 1000.0 * 1.85200, 3); return NM; } @@ -82,7 +95,7 @@ public: */ static const CLengthUnit &ft() { - static CLengthUnit ft(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot"), "ft", false, false, 0.3048, CMeasurementPrefix::One(), 0); + static CLengthUnit ft(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot"), "ft", 0.3048, 0); return ft; } @@ -92,7 +105,7 @@ public: */ static const CLengthUnit &km() { - static CLengthUnit km(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilometer"), "km", true, false, CMeasurementPrefix::k().getFactor(), CMeasurementPrefix::k(), 3); + static CLengthUnit km(CMeasurementPrefix::k(), m(), 3); return km; } @@ -102,7 +115,7 @@ public: */ static const CLengthUnit &cm() { - static CLengthUnit cm(QT_TRANSLATE_NOOP("CMeasurementUnit", "centimeter"), "cm", true, false, CMeasurementPrefix::c().getFactor(), CMeasurementPrefix::c(), 1); + static CLengthUnit cm(CMeasurementPrefix::c(), m(), 1); return cm; } @@ -112,7 +125,7 @@ public: */ static const CLengthUnit &mi() { - static CLengthUnit mi(QT_TRANSLATE_NOOP("CMeasurementUnit", "mile"), "mi", false, false, 1609.344, CMeasurementPrefix::None(), 3); + static CLengthUnit mi(QT_TRANSLATE_NOOP("CMeasurementUnit", "mile"), "mi", 1609.344, 3); return mi; } @@ -120,17 +133,17 @@ public: * \brief Statute mile * \return */ - static const CLengthUnit &miStatute() + static const CLengthUnit &SM() { - static CLengthUnit mi(QT_TRANSLATE_NOOP("CMeasurementUnit", "mile(statute)"), "mi(statute)", false, false, 1609.3472, CMeasurementPrefix::None(), 3); - return mi; + static CLengthUnit sm(QT_TRANSLATE_NOOP("CMeasurementUnit", "statute miles"), "SM", 1609.3472, 3); + return sm; } /*! * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -140,27 +153,12 @@ public: u.append(CLengthUnit::km()); u.append(CLengthUnit::m()); u.append(CLengthUnit::mi()); - u.append(CLengthUnit::miStatute()); + u.append(CLengthUnit::SM()); u.append(CLengthUnit::NM()); } return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CLengthUnit &fromUnitName(const QString &unitName) - { - const QList &units = CLengthUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CLengthUnit::m(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -170,7 +168,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CLengthUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -183,38 +181,30 @@ private: /*! * \brief Constructor angle units: Radian, degree * \param name - * \param unitName - * \param isSiUnit - * \param conversionFactorToSI - * \param multiplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CAngleUnit(const QString &name, const QString &unitName, bool isSiUnit, double conversionFactorToSI = 1.0, - const CMeasurementPrefix &multiplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, - double epsilon = 1E-9, UnitConverter converterToSi = 0, UnitConverter converterFromSi = 0) : - CMeasurementUnit(name, unitName, "angle", isSiUnit, false, conversionFactorToSI, - multiplier, displayDigits, epsilon, converterToSi, converterFromSi) {} + CAngleUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} /*! - * \brief Special conversion for sexagesimal degrees - * \param value - * \return + * \brief Constructor angle units: Sexagesimal + * \param name + * \param symbol + * \param converter + * \param displayDigits + * \param epsilon */ - static double conversionSexagesimalToSi(const CMeasurementUnit &angleUnit, double value); - - /*! - * \brief Special conversion for sexagesimal degrees - * \param value - * \return - */ - static double conversionSexagesimalFromSi(const CMeasurementUnit &angleUnit, double value); + CAngleUnit(const QString &name, const QString &symbol, Converter *converter, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, converter, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CAngleUnit() : CMeasurementUnit("radian", "rad", "angle", true, false) {} + CAngleUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor @@ -223,13 +213,19 @@ public: CAngleUnit(const CAngleUnit &other) : CMeasurementUnit(other) {} /*! - * \brief Special conversion to QString for sexagesimal degrees. + * \brief Default unit + * \return + */ + static const CAngleUnit &defaultUnit() { return deg(); } + + /*! + * \brief Override for sexagesimal degrees. * \param value * \param digits * \param i18n * \return */ - virtual QString toQStringRounded(double value, int digits = -1, bool i18n = false) const; + virtual QString makeRoundedQString(double value, int digits = -1, bool i18n = false) const; /*! * \brief Radians @@ -237,7 +233,7 @@ public: */ static const CAngleUnit &rad() { - static CAngleUnit rad(QT_TRANSLATE_NOOP("CMeasurementUnit", "radian"), "rad", true); + static CAngleUnit rad(QT_TRANSLATE_NOOP("CMeasurementUnit", "radian"), "rad", 180.0 / M_PI); return rad; } @@ -247,25 +243,39 @@ public: */ static const CAngleUnit °() { - static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degree"), QT_TRANSLATE_NOOP("CMeasurementUnit", "deg"), false, M_PI / 180); + static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degree"), QT_TRANSLATE_NOOP("CMeasurementUnit", "deg"), 1); return deg; } /*! - * \brief Sexagesimal degree (degree, minute, seconds) + * \brief Sexagesimal degree (degrees, minutes, seconds, decimal seconds) * \return */ static const CAngleUnit &sexagesimalDeg() { - static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "segadecimal degree"), "segd", false, M_PI / 180, - CMeasurementPrefix::One(), 0, 1E-9, CAngleUnit::conversionSexagesimalToSi, CAngleUnit::conversionSexagesimalFromSi); return deg; + static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degrees minutes seconds"), "DMS", new SubdivisionConverter2<60, 100, 60, 100>, 0); + return deg; + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1 %L2'%L3\""); + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%-L1 %L2'%L3\""); + } + + /*! + * \brief Sexagesimal degree (degrees, minutes, decimal minutes) + * \return + */ + static const CAngleUnit &sexagesimalDegMin() + { + static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degrees minutes"), "MinDec", new SubdivisionConverter<60, 100>, 2); + return deg; + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1 %L2'"); + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1 %L2'"); } /*! * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -273,25 +283,11 @@ public: u.append(CAngleUnit::deg()); u.append(CAngleUnit::rad()); u.append(CAngleUnit::sexagesimalDeg()); + u.append(CAngleUnit::sexagesimalDegMin()); } return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CAngleUnit &fromUnitName(const QString &unitName) - { - const QList &units = CAngleUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CAngleUnit::rad(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -301,7 +297,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CAngleUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -312,24 +308,31 @@ class CFrequencyUnit : public CMeasurementUnit { private: /*! - * Constructor - * \brief CFrequencyUnit + * Constructor frequency unit * \param name - * \param unitName - * \param isSiUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CFrequencyUnit(const QString &name, const QString &unitName, bool isSiUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "frequency", isSiUnit, false, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CFrequencyUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} + + /*! + * Constructor frequency unit + * \param prefix + * \param base + * \param displayDigits + * \param epsilon + */ + CFrequencyUnit(const CMeasurementPrefix &prefix, const CFrequencyUnit &base, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(base, prefix, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CFrequencyUnit() : CMeasurementUnit("hertz", "Hz", "frequency", true, false) {} + CFrequencyUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor @@ -337,13 +340,19 @@ public: */ CFrequencyUnit(const CFrequencyUnit &other) : CMeasurementUnit(other) {} + /*! + * \brief Default unit + * \return + */ + static const CFrequencyUnit &defaultUnit() { return Hz(); } + /*! * \brief Hertz * \return */ static const CFrequencyUnit &Hz() { - static CFrequencyUnit Hz(QT_TRANSLATE_NOOP("CMeasurementUnit", "hertz"), "Hz", true); + static CFrequencyUnit Hz(QT_TRANSLATE_NOOP("CMeasurementUnit", "hertz"), "Hz", 1); return Hz; } @@ -353,7 +362,7 @@ public: */ static const CFrequencyUnit &kHz() { - static CFrequencyUnit kHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilohertz"), "kHz", true, CMeasurementPrefix::k().getFactor(), CMeasurementPrefix::k(), 1); + static CFrequencyUnit kHz(CMeasurementPrefix::k(), Hz(), 1); return kHz; } @@ -363,7 +372,7 @@ public: */ static const CFrequencyUnit &MHz() { - static CFrequencyUnit MHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "megahertz"), "MHz", false, CMeasurementPrefix::M().getFactor(), CMeasurementPrefix::M(), 2); + static CFrequencyUnit MHz(CMeasurementPrefix::M(), Hz(), 2); return MHz; } @@ -373,7 +382,7 @@ public: */ static const CFrequencyUnit &GHz() { - static CFrequencyUnit GHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "gigahertz"), "GHz", true, CMeasurementPrefix::G().getFactor(), CMeasurementPrefix::G(), 2); + static CFrequencyUnit GHz(CMeasurementPrefix::G(), Hz(), 2); return GHz; } @@ -381,7 +390,7 @@ public: * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -394,21 +403,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CFrequencyUnit &fromUnitName(const QString &unitName) - { - const QList &units = CFrequencyUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CFrequencyUnit::Hz(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -418,7 +412,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CFrequencyUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -431,22 +425,29 @@ private: /*! * \brief Constructor mass units * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CMassUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "mass", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CMassUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} + + /*! + * \brief Constructor mass units + * \param prefix + * \param base + * \param displayDigits + * \param epsilon + */ + CMassUnit(const CMeasurementPrefix &prefix, const CMassUnit &base, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(base, prefix, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CMassUnit() : CMeasurementUnit("kilogram", "kg", "mass", true, true, 1.0, CMeasurementPrefix::k(), 1) {} + CMassUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor @@ -454,13 +455,19 @@ public: */ CMassUnit(const CMassUnit &other) : CMeasurementUnit(other) {} + /*! + * \brief Default unit + * \return + */ + static const CMassUnit &defaultUnit() { return kg(); } + /*! * \brief Kilogram, SI base unit * \return */ static const CMassUnit &kg() { - static CMassUnit kg(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilogram"), "kg", true, true, 1.0, CMeasurementPrefix::k(), 1); + static CMassUnit kg(CMeasurementPrefix::k(), g(), 1); return kg; } @@ -470,7 +477,7 @@ public: */ static const CMassUnit &g() { - static CMassUnit g(QT_TRANSLATE_NOOP("CMeasurementUnit", "gram"), "g", true, false, 1.0 / 1000.0, CMeasurementPrefix::One(), 0); + static CMassUnit g(QT_TRANSLATE_NOOP("CMeasurementUnit", "gram"), "g", 0.001, 0); return g; } @@ -480,7 +487,7 @@ public: */ static const CMassUnit &t() { - static CMassUnit t(QT_TRANSLATE_NOOP("CMeasurementUnit", "tonne"), "t", false, false, 1000.0, CMeasurementPrefix::One(), 3); + static CMassUnit t(QT_TRANSLATE_NOOP("CMeasurementUnit", "tonne"), "t", 1000.0, 3); return t; } @@ -490,7 +497,7 @@ public: */ static const CMassUnit &lb() { - static CMassUnit lbs(QT_TRANSLATE_NOOP("CMeasurementUnit", "pound"), "lb", false, false, 0.45359237, CMeasurementPrefix::One(), 1); + static CMassUnit lbs(QT_TRANSLATE_NOOP("CMeasurementUnit", "pound"), "lb", 0.45359237, 1); return lbs; } @@ -498,7 +505,7 @@ public: * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -511,21 +518,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CMassUnit &fromUnitName(const QString &unitName) - { - const QList &units = CMassUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CMassUnit::kg(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -535,7 +527,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CMassUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -546,24 +538,31 @@ class CPressureUnit : public CMeasurementUnit { private: /*! - * Constructor - * \brief Pressure unit + * \brief Pressure unit constructor * \param name - * \param unitName - * \param isSiUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CPressureUnit(const QString &name, const QString &unitName, bool isSiUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "pressure", isSiUnit, false, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CPressureUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} + + /*! + * \brief Pressure unit constructor + * \param prefix + * \param base + * \param displayDigits + * \param epsilon + */ + CPressureUnit(const CMeasurementPrefix &prefix, const CPressureUnit &base, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(base, prefix, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CPressureUnit() : CMeasurementUnit("pascal", "Pa", "pressure", true, false) {} + CPressureUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor @@ -571,13 +570,19 @@ public: */ CPressureUnit(const CPressureUnit &other) : CMeasurementUnit(other) {} + /*! + * \brief Default unit + * \return + */ + static const CPressureUnit &defaultUnit() { return hPa(); } + /*! * \brief Pascal * \return */ static const CPressureUnit &Pa() { - static CPressureUnit Pa(QT_TRANSLATE_NOOP("CMeasurementUnit", "pascal"), "Pa", true); + static CPressureUnit Pa(QT_TRANSLATE_NOOP("CMeasurementUnit", "pascal"), "Pa", 0.01); return Pa; } @@ -587,7 +592,7 @@ public: */ static const CPressureUnit &hPa() { - static CPressureUnit hPa(QT_TRANSLATE_NOOP("CMeasurementUnit", "hectopascal"), "hPa", true, CMeasurementPrefix::h().getFactor(), CMeasurementPrefix::h()); + static CPressureUnit hPa(CMeasurementPrefix::h(), Pa()); return hPa; } @@ -597,7 +602,7 @@ public: */ static const CPressureUnit &psi() { - static CPressureUnit psi(QT_TRANSLATE_NOOP("CMeasurementUnit", "pounds per square inch"), "psi", false, 6894.8, CMeasurementPrefix::One(), 2); + static CPressureUnit psi(QT_TRANSLATE_NOOP("CMeasurementUnit", "pounds per square inch"), "psi", 68.948, 2); return psi; } @@ -607,7 +612,7 @@ public: */ static const CPressureUnit &bar() { - static CPressureUnit bar(QT_TRANSLATE_NOOP("CMeasurementUnit", "bar"), "bar", false, 1E5); + static CPressureUnit bar(QT_TRANSLATE_NOOP("CMeasurementUnit", "bar"), "bar", 1000, 1, 1E5); return bar; } @@ -617,7 +622,7 @@ public: */ static const CPressureUnit &mbar() { - static CPressureUnit bar(QT_TRANSLATE_NOOP("CMeasurementUnit", "millibar"), "bar", false, 1E2); + static CPressureUnit bar(CMeasurementPrefix::m(), bar(), 1, 1E2); return bar; } @@ -627,15 +632,25 @@ public: */ static const CPressureUnit &inHg() { - static CPressureUnit inhg(QT_TRANSLATE_NOOP("CMeasurementUnit", "inch of mercury"), "inHg", false, 3386.389); + static CPressureUnit inhg(QT_TRANSLATE_NOOP("CMeasurementUnit", "inch of mercury"), "inHg", 33.86389); return inhg; } + /*! + * \brief Millimeter of mercury + * \return + */ + static const CPressureUnit &mmHg() + { + static CPressureUnit mmhg(QT_TRANSLATE_NOOP("CMeasurementUnit", "millimeter of mercury"), "mmHg", 860.142806); + return mmhg; + } + /*! * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -643,27 +658,13 @@ public: u.append(CPressureUnit::bar()); u.append(CPressureUnit::hPa()); u.append(CPressureUnit::inHg()); + u.append(CPressureUnit::mmHg()); u.append(CPressureUnit::mbar()); u.append(CPressureUnit::psi()); } return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CPressureUnit &fromUnitName(const QString &unitName) - { - const QList &units = CPressureUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CPressureUnit::Pa(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -673,7 +674,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CPressureUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -682,62 +683,36 @@ protected: */ class CTemperatureUnit : public CMeasurementUnit { -private: - double m_conversionOffsetToSi; - private: /*! * Constructor temperature unit * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param temperatureOffsetToSI - * \param mulitplier + * \param symbol + * \param factor + * \param offset * \param displayDigits * \param epsilon */ - CTemperatureUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, double temperatureOffsetToSI = 0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "temperature", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon), m_conversionOffsetToSi(temperatureOffsetToSI) {} - -protected: - /*! - * \brief Convert to SI conversion unit, specific for temperature - * \param value - * \return - */ - virtual double conversionToSiConversionUnit(double value) const; - - /*! - * \brief Convert from SI conversion unit, specific for temperature - * \param value - * \return - */ - virtual double conversionFromSiConversionUnit(double value) const; + CTemperatureUnit(const QString &name, const QString &symbol, double factor, double offset, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, offset, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CTemperatureUnit() : CMeasurementUnit("Kelvin", "K", "temperature", true, true) {} + CTemperatureUnit() : CMeasurementUnit(defaultUnit()) {} /*! * \brief Copy constructor * \param other */ - CTemperatureUnit(const CTemperatureUnit &other) : CMeasurementUnit(other), m_conversionOffsetToSi(other.m_conversionOffsetToSi) {} + CTemperatureUnit(const CTemperatureUnit &other) : CMeasurementUnit(other) {} /*! - * Assigment operator + * \brief Default unit + * \return */ - CTemperatureUnit &operator =(const CTemperatureUnit &other) - { - if (this == &other) return *this; - CMeasurementUnit::operator = (other); - this->m_conversionOffsetToSi = other.m_conversionOffsetToSi; - return *this; - } + static const CTemperatureUnit &defaultUnit() { return C(); } /*! * \brief Kelvin @@ -745,7 +720,7 @@ public: */ static const CTemperatureUnit &K() { - static CTemperatureUnit K(QT_TRANSLATE_NOOP("CMeasurementUnit", "Kelvin"), "K", true, true); + static CTemperatureUnit K(QT_TRANSLATE_NOOP("CMeasurementUnit", "Kelvin"), "K", 1, 273.15); return K; } @@ -755,7 +730,7 @@ public: */ static const CTemperatureUnit &C() { - static CTemperatureUnit C(QT_TRANSLATE_NOOP("CMeasurementUnit", "centigrade"), QT_TRANSLATE_NOOP("CMeasurementUnit", "C"), false, false, 1.0, 273.15); + static CTemperatureUnit C(QT_TRANSLATE_NOOP("CMeasurementUnit", "centigrade"), QT_TRANSLATE_NOOP("CMeasurementUnit", "C"), 1, 0); return C; } @@ -765,7 +740,7 @@ public: */ static const CTemperatureUnit &F() { - static CTemperatureUnit F(QT_TRANSLATE_NOOP("CMeasurementUnit", "Fahrenheit"), QT_TRANSLATE_NOOP("CMeasurementUnit", "F"), false, false, 5.0 / 9.0, 459.67); + static CTemperatureUnit F(QT_TRANSLATE_NOOP("CMeasurementUnit", "Fahrenheit"), QT_TRANSLATE_NOOP("CMeasurementUnit", "F"), 5.0 / 9.0, 32); return F; } @@ -773,7 +748,7 @@ public: * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -785,21 +760,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CTemperatureUnit &fromUnitName(const QString &unitName) - { - const QList &units = CTemperatureUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CTemperatureUnit::K(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -809,7 +769,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CTemperatureUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -820,25 +780,21 @@ class CSpeedUnit : public CMeasurementUnit { private: /*! - * Constructor * \brief Speed unit constructor * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CSpeedUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "speed", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CSpeedUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CSpeedUnit() : CMeasurementUnit("meters/second", "m/s", "speed", true, false) {} + CSpeedUnit() : CMeasurementUnit(defaultUnit()) {} /*! * Constructor, allows to implement methods in base class @@ -846,13 +802,19 @@ public: */ CSpeedUnit(const CSpeedUnit &other) : CMeasurementUnit(other) {} + /*! + * Default unit + * \return + */ + static const CSpeedUnit &defaultUnit() { return m_s(); } + /*! * \brief Meter/second m/s * \return */ static const CSpeedUnit &m_s() { - static CSpeedUnit ms(QT_TRANSLATE_NOOP("CMeasurementUnit", "meters/second"), "m/s", true, false); + static CSpeedUnit ms(QT_TRANSLATE_NOOP("CMeasurementUnit", "meters/second"), "m/s", 1); return ms; } @@ -862,7 +824,7 @@ public: */ static const CSpeedUnit &kts() { - static CSpeedUnit kts(QT_TRANSLATE_NOOP("CMeasurementUnit", "knot"), "kts", false, false, 1852.0 / 3600.0, CMeasurementPrefix::One(), 1); + static CSpeedUnit kts(QT_TRANSLATE_NOOP("CMeasurementUnit", "knot"), "kts", 1852.0 / 3600.0, 1); return kts; } @@ -872,7 +834,7 @@ public: */ static const CSpeedUnit &NM_h() { - static CSpeedUnit NMh(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical miles/hour"), "NM/h", false, false, 1852.0 / 3600.0, CMeasurementPrefix::One(), 1); + static CSpeedUnit NMh(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical miles/hour"), "NM/h", 1852.0 / 3600.0, 1); return NMh; } @@ -882,7 +844,7 @@ public: */ static const CSpeedUnit &ft_s() { - static CSpeedUnit fts(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/second"), "ft/s", false, false, 0.3048, CMeasurementPrefix::One(), 0); + static CSpeedUnit fts(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/second"), "ft/s", 0.3048, 0); return fts; } @@ -892,7 +854,7 @@ public: */ static const CSpeedUnit &ft_min() { - static CSpeedUnit ftmin(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/minute"), "ft/min", false, false, 0.3048 / 60.0, CMeasurementPrefix::One(), 0); + static CSpeedUnit ftmin(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/minute"), "ft/min", 0.3048 / 60.0, 0); return ftmin; } @@ -902,7 +864,7 @@ public: */ static const CSpeedUnit &km_h() { - static CSpeedUnit kmh(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilometers/hour"), "km/h", false, false, 1.0 / 3.6, CMeasurementPrefix::One(), 1); + static CSpeedUnit kmh(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilometers/hour"), "km/h", 1.0 / 3.6, 1); return kmh; } @@ -910,7 +872,7 @@ public: * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -925,21 +887,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CSpeedUnit &fromUnitName(const QString &unitName) - { - const QList &units = CSpeedUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CSpeedUnit::m_s(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -949,7 +896,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CSpeedUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -960,25 +907,42 @@ class CTimeUnit : public CMeasurementUnit { private: /*! - * Constructor * \brief Time unit constructor * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CTimeUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "time", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CTimeUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} + + /*! + * \brief Time unit constructor + * \param prefix + * \param base + * \param displayDigits + * \param epsilon + */ + CTimeUnit(const CMeasurementPrefix &prefix, const CTimeUnit &base, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(base, prefix, displayDigits, epsilon) {} + + /*! + * \brief Time unit constructor + * \param name + * \param symbol + * \param converter + * \param displayDigits + * \param epsilon + */ + CTimeUnit(const QString &name, const QString &symbol, Converter *converter, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, converter, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CTimeUnit() : CMeasurementUnit("second", "s", "time", true, true, 1, CMeasurementPrefix::None()) {} + CTimeUnit() : CMeasurementUnit(defaultUnit()) {} /*! * Constructor, allows to implement methods in base class @@ -986,13 +950,28 @@ public: */ CTimeUnit(const CTimeUnit &other) : CMeasurementUnit(other) {} + /*! + * Default unit + * \return + */ + static const CTimeUnit &defaultUnit() { return s(); } + + /*! + * \brief Override for subdivisional units. + * \param value + * \param digits + * \param i18n + * \return + */ + virtual QString makeRoundedQString(double value, int digits = -1, bool i18n = false) const; + /*! * \brief Second s * \return */ static const CTimeUnit &s() { - static CTimeUnit s(QT_TRANSLATE_NOOP("CMeasurementUnit", "second"), "s", true, true, 1, CMeasurementPrefix::None(), 1); + static CTimeUnit s(QT_TRANSLATE_NOOP("CMeasurementUnit", "second"), "s", 1, 1); return s; } @@ -1002,7 +981,7 @@ public: */ static const CTimeUnit &ms() { - static CTimeUnit ms(QT_TRANSLATE_NOOP("CMeasurementUnit", "millisecond"), "ms", true, false, 1E-03, CMeasurementPrefix::m(), 0); + static CTimeUnit ms(CMeasurementPrefix::m(), s(), 0); return ms; } @@ -1012,7 +991,7 @@ public: */ static const CTimeUnit &h() { - static CTimeUnit h(QT_TRANSLATE_NOOP("CMeasurementUnit", "hour"), "h", false, false, 3600, CMeasurementPrefix::None(), 1); + static CTimeUnit h(QT_TRANSLATE_NOOP("CMeasurementUnit", "hour"), "h", 3600, 1); return h; } @@ -1022,7 +1001,7 @@ public: */ static const CTimeUnit &min() { - static CTimeUnit min(QT_TRANSLATE_NOOP("CMeasurementUnit", "minute"), "min", false, false, 60, CMeasurementPrefix::None(), 2); + static CTimeUnit min(QT_TRANSLATE_NOOP("CMeasurementUnit", "minute"), "min", 60, 2); return min; } @@ -1032,15 +1011,48 @@ public: */ static const CTimeUnit &d() { - static CTimeUnit day(QT_TRANSLATE_NOOP("CMeasurementUnit", "day"), "d", false, false, 3600 * 24, CMeasurementPrefix::None(), 1); + static CTimeUnit day(QT_TRANSLATE_NOOP("CMeasurementUnit", "day"), "d", 3600 * 24, 1); return day; } + /*! + * \brief Hours, minutes, seconds + */ + static const CTimeUnit &hms() + { + static CTimeUnit hms(QT_TRANSLATE_NOOP("CMeasurementUnit", "hours minutes seconds"), "hms", new SubdivisionConverter2<60, 100, 60, 100>(3600), 0); + return hms; + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1h%L2m%L3s"); + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%-L1h%L2m%L3s"); + } + + /*! + * \brief Hours, minutes + */ + static const CTimeUnit &hrmin() + { + static CTimeUnit hrmin(QT_TRANSLATE_NOOP("CMeasurementUnit", "hours minutes"), "hm", new SubdivisionConverter<60, 100>(3600), 1); + return hrmin; + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1h%L2m"); + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1h%L2m"); + } + + /*! + * \brief Minutes, seconds + */ + static const CTimeUnit &minsec() + { + static CTimeUnit minsec(QT_TRANSLATE_NOOP("CMeasurementUnit", "minutes seconds"), "minsec", new SubdivisionConverter<60, 100>(60), 0); + return minsec; + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1m%L2s"); + (void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1m%L2s"); + } + /*! * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -1054,21 +1066,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CTimeUnit &fromUnitName(const QString &unitName) - { - const QList &units = CTimeUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CTimeUnit::s(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -1078,7 +1075,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CTimeUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; @@ -1089,39 +1086,41 @@ class CAccelerationUnit : public CMeasurementUnit { private: /*! - * Constructor * \brief Acceleration unit constructor * \param name - * \param unitName - * \param isSiUnit - * \param isSIBaseUnit - * \param conversionFactorToSI - * \param mulitplier + * \param symbol + * \param factor * \param displayDigits * \param epsilon */ - CAccelerationUnit(const QString &name, const QString &unitName, bool isSiUnit, bool isSIBaseUnit, double conversionFactorToSI = 1.0, const CMeasurementPrefix &mulitplier = CMeasurementPrefix::One(), qint32 displayDigits = 2, double epsilon = 1E-9) : - CMeasurementUnit(name, unitName, "acceleration", isSiUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {} + CAccelerationUnit(const QString &name, const QString &symbol, double factor, int displayDigits = 2, double epsilon = 1E-9) : + CMeasurementUnit(name, symbol, factor, displayDigits, epsilon) {} public: /*! * Default constructor, required for Qt Metasystem */ - CAccelerationUnit() : CMeasurementUnit("meter/second^2", "m/s^2", "acceleration", true, false, 1, CMeasurementPrefix::None(), 1) {} + CAccelerationUnit() : CMeasurementUnit(defaultUnit()) {} /*! - * Constructor, allows to implement methods in base class + * Copy constructor * \param other */ CAccelerationUnit(const CAccelerationUnit &other) : CMeasurementUnit(other) {} + /*! + * Default unit + * \return + */ + static const CAccelerationUnit &defaultUnit() { return m_s2(); } + /*! * \brief Meter/second^2 (m/s^2) * \return */ static const CAccelerationUnit &m_s2() { - static CAccelerationUnit ms2(QT_TRANSLATE_NOOP("CMeasurementUnit", "meters/second^2"), QT_TRANSLATE_NOOP("CMeasurementUnit", "m/s^2"), true, false, 1, CMeasurementPrefix::None(), 1); + static CAccelerationUnit ms2(QT_TRANSLATE_NOOP("CMeasurementUnit", "meters/second^2"), QT_TRANSLATE_NOOP("CMeasurementUnit", "m/s^2"), 1, 1); return ms2; } @@ -1131,7 +1130,7 @@ public: */ static const CAccelerationUnit &ft_s2() { - static CAccelerationUnit fts2(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/second^2"), QT_TRANSLATE_NOOP("CMeasurementUnit", "ft/s^2"), true, false, 3.28084, CMeasurementPrefix::m(), 0); + static CAccelerationUnit fts2(QT_TRANSLATE_NOOP("CMeasurementUnit", "feet/second^2"), QT_TRANSLATE_NOOP("CMeasurementUnit", "ft/s^2"), 3.28084, 0); return fts2; } @@ -1139,7 +1138,7 @@ public: * \brief All units * \return */ - static const QList &units() + static const QList &allUnits() { static QList u; if (u.isEmpty()) @@ -1150,21 +1149,6 @@ public: return u; } - /*! - * \brief Unit from name - * \param unitName must be valid! - * \return - */ - static const CAccelerationUnit &fromUnitName(const QString &unitName) - { - const QList &units = CAccelerationUnit::units(); - for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getUnitName() == unitName) return (units.at(i)); - } - qFatal("Illegal unit name"); - return CAccelerationUnit::m_s2(); // just suppress "not all control paths return a value" - } - protected: /*! * \brief Stream from DBus @@ -1174,7 +1158,7 @@ protected: { QString unitName; argument >> unitName; - (*this) = CAccelerationUnit::fromUnitName(unitName); + (*this) = CMeasurementUnit::unitFromSymbol(unitName); } }; diff --git a/tests/blackmisc/testaviation.cpp b/tests/blackmisc/testaviation.cpp index 7bec3cda6..1956ea577 100644 --- a/tests/blackmisc/testaviation.cpp +++ b/tests/blackmisc/testaviation.cpp @@ -37,11 +37,11 @@ void CTestAviation::headingBasics() QVERIFY2(h4 == h1, "Values shall be equal"); h1 -= h1; - QVERIFY2(h1.unitValueToDouble() == 0, "Value shall be 0"); + QVERIFY2(h1.value() == 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"); + QVERIFY2(h2.value() == 360, "Value shall be 360"); } /* diff --git a/tests/blackmisc/testgeo.cpp b/tests/blackmisc/testgeo.cpp index 211bd098c..8c5b5b21b 100644 --- a/tests/blackmisc/testgeo.cpp +++ b/tests/blackmisc/testgeo.cpp @@ -14,7 +14,7 @@ void CTestGeo::geoBasics() CLatitude lati(10, CAngleUnit::deg()); QVERIFY2(lati * 2 == lati + lati, "Latitude addition should be equal"); lati += CLatitude(20, CAngleUnit::deg()); - QVERIFY2(lati.unitValueToDoubleRounded() == 30.0, "Latitude should be 30 degrees"); + QVERIFY2(lati.valueRounded() == 30.0, "Latitude should be 30 degrees"); double lat = 27.999999, lon = 86.999999, h = 8820.999999; // Mt Everest CCoordinateGeodetic startGeoVec(lat, lon, h); diff --git a/tests/blackmisc/testphysicalquantities.cpp b/tests/blackmisc/testphysicalquantities.cpp index 2a918a458..a958046de 100644 --- a/tests/blackmisc/testphysicalquantities.cpp +++ b/tests/blackmisc/testphysicalquantities.cpp @@ -15,8 +15,6 @@ namespace BlackMiscTest */ void CTestPhysicalQuantities::unitsBasics() { - QVERIFY2(CMeasurementPrefix::k() > CMeasurementPrefix::h(), "kilo > hecto"); - // some tests on units CLengthUnit du1 = CLengthUnit::m(); // Copy CLengthUnit du2 = CLengthUnit::m(); // Copy @@ -25,7 +23,6 @@ void CTestPhysicalQuantities::unitsBasics() du2 = CLengthUnit::m(); // Copy QVERIFY2(du1 == du2, "Compare by value 2"); QVERIFY2(CLengthUnit::m() == CLengthUnit::m(), "Compare by value"); - QVERIFY2(CMeasurementPrefix::h() < CMeasurementPrefix::M(), "hecto < mega"); CFrequencyUnit fu1 = CFrequencyUnit::Hz(); QVERIFY2(fu1 != du1, "Hz must not be meter"); @@ -54,12 +51,12 @@ void CTestPhysicalQuantities::lengthBasics() // epsilon tests d1 = d2; // both in same unit - d1.addUnitValue(d1.getUnit().getEpsilon()); // this should be still the same + d1.addValueSameUnit(d1.getUnit().getEpsilon() / 2.0); // this should be still the same QVERIFY2(d1 == d2, "Epsilon: 100cm + epsilon shall be 100cm"); QVERIFY2(!(d1 != d2), "Epsilon: 100cm + epsilon shall be still 100cm"); QVERIFY2(!(d1 > d2), "d1 shall not be greater"); - d1.addUnitValue(d1.getUnit().getEpsilon()); // now over epsilon threshold + d1.addValueSameUnit(d1.getUnit().getEpsilon()); // now over epsilon threshold QVERIFY2(d1 != d2, "Epsilon exceeded: 100 cm + 2 epsilon shall not be 100cm"); QVERIFY2(d1 > d2, "d1 shall be greater"); } @@ -82,8 +79,8 @@ void CTestPhysicalQuantities::frequencyTests() { CFrequency f1(1, CFrequencyUnit::MHz()); QVERIFY2(f1.valueRounded(CFrequencyUnit::kHz(), 2) == 1000, "Mega is 1000kHz"); - QVERIFY2(f1.unitValueToDouble() == 1 , "1MHz"); - QVERIFY2(f1.convertedSiValueToDouble() == 1000000 , "1E6 Hz"); + QVERIFY2(f1.value() == 1 , "1MHz"); + QVERIFY2(f1.value(CFrequencyUnit::defaultUnit()) == 1000000 , "1E6 Hz"); CFrequency f2(CMeasurementPrefix::M().toDouble(), CFrequencyUnit::Hz()) ; // 1 Megahertz QVERIFY2(f1 == f2 , "MHz is 1E6 Hz"); } @@ -96,9 +93,13 @@ void CTestPhysicalQuantities::angleTests() CAngle a1(180, CAngleUnit::deg()); CAngle a2(1.5 * CAngle::PI(), CAngleUnit::rad()); CAngle a3(35.4336, CAngleUnit::sexagesimalDeg()); // 35.72666 + CAngle a4(35.436, CAngleUnit::sexagesimalDegMin()); // 35.72666 + CAngle a5(-60.3015, CAngleUnit::sexagesimalDeg()); // negative angles = west longitude or south latitude a2.switchUnit(CAngleUnit::deg()); QVERIFY2(a1.piFactor() == 1, qPrintable(QString("Pi should be 1PI, not %1").arg(a1.piFactor()))); QVERIFY2(a3.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); + QVERIFY2(a4.valueRounded(CAngleUnit::deg()) == 35.73, "Expecting 35.73"); + QVERIFY2(a5.valueRounded(CAngleUnit::deg(), 4) == -60.5042, "Expecting -60.5042"); } /* @@ -107,11 +108,11 @@ void CTestPhysicalQuantities::angleTests() void CTestPhysicalQuantities::massTests() { CMass w1(1000, CMassUnit::kg()); - CMass w2(w1.unitValueToDouble(), CMassUnit::kg()); + CMass w2(w1.value(), CMassUnit::kg()); w2.switchUnit(CMassUnit::t()); - QVERIFY2(w2.unitValueToDouble() == 1, "1tonne shall be 1000kg"); + QVERIFY2(w2.value() == 1, "1tonne shall be 1000kg"); w2.switchUnit(CMassUnit::lb()); - QVERIFY2(w2.unitValueToDoubleRounded(2) == 2204.62, "1tonne shall be 2204pounds"); + QVERIFY2(w2.valueRounded(2) == 2204.62, "1tonne shall be 2204pounds"); QVERIFY2(w1 == w2, "Masses shall be equal"); } @@ -127,7 +128,7 @@ void CTestPhysicalQuantities::pressureTests() // does not match exactly QVERIFY2(p1 != p2, "Standard pressure test little difference"); - QVERIFY2(p1.unitValueToDouble() == p4.unitValueToDouble(), "mbar/hPa test"); + QVERIFY2(p1.value() == p4.value(), "mbar/hPa test"); } /* @@ -139,19 +140,25 @@ void CTestPhysicalQuantities::temperatureTests() CTemperature t2(1, CTemperatureUnit::F()); // 1F CTemperature t3(220.15, CTemperatureUnit::F()); CTemperature t4(10, CTemperatureUnit::F()); - QVERIFY2(t1.convertedSiValueToDoubleRounded() == 273.15, qPrintable(QString("0C shall be 273.15K, not %1 K").arg(t1.convertedSiValueToDoubleRounded()))); + QVERIFY2(t1.valueRounded(CTemperatureUnit::K()) == 273.15, qPrintable(QString("0C shall be 273.15K, not %1 K").arg(t1.valueRounded(CTemperatureUnit::K())))); QVERIFY2(t2.valueRounded(CTemperatureUnit::C()) == -17.22, qPrintable(QString("1F shall be -17.22C, not %1 C").arg(t2.valueRounded(CTemperatureUnit::C())))); QVERIFY2(t3.valueRounded(CTemperatureUnit::C()) == 104.53, qPrintable(QString("220.15F shall be 104.53C, not %1 C").arg(t3.valueRounded(CTemperatureUnit::C())))); QVERIFY2(t4.valueRounded(CTemperatureUnit::K()) == 260.93, qPrintable(QString("10F shall be 260.93K, not %1 K").arg(t4.valueRounded(CTemperatureUnit::K())))); } /* - * Temperature tests + * Time tests */ void CTestPhysicalQuantities::timeTests() { CTime t1(1, CTimeUnit::h()); - QVERIFY2(t1.convertedSiValueToDouble() == 3600, "1hour shall be 3600s"); + CTime t2(1.5, CTimeUnit::h()); + CTime t3(1.25, CTimeUnit::min()); + CTime t4(1.0101, CTimeUnit::hms()); + QVERIFY2(t1.value(CTimeUnit::defaultUnit()) == 3600, "1hour shall be 3600s"); + QVERIFY2(t2.value(CTimeUnit::hrmin()) == 1.30, "1.5hour shall be 1h30m"); + QVERIFY2(t3.value(CTimeUnit::minsec()) == 1.15, "1.25min shall be 1m15s"); + QVERIFY2(t4.value(CTimeUnit::s()) == 3661, "1h01m01s shall be 3661s"); } /* @@ -160,13 +167,13 @@ void CTestPhysicalQuantities::timeTests() void CTestPhysicalQuantities::accelerationTests() { CLength oneMeter(1, CLengthUnit::m()); - double ftFactor = oneMeter.switchUnit(CLengthUnit::ft()).unitValueToDouble(); + double ftFactor = oneMeter.switchUnit(CLengthUnit::ft()).value(); CAcceleration a1(10.0, CAccelerationUnit::m_s2()); CAcceleration a2(a1); a1.switchUnit(CAccelerationUnit::ft_s2()); QVERIFY2(a1 == a2, "Accelerations should be similar"); - QVERIFY2(BlackMisc::Math::CMath::round(a1.unitValueToDouble() * ftFactor, 6) == a2.unitValueToDoubleRounded(6), + QVERIFY2(BlackMisc::Math::CMath::round(a1.value() * ftFactor, 6) == a2.valueRounded(6), "Numerical values should be equal"); } @@ -177,13 +184,13 @@ void CTestPhysicalQuantities::memoryTests() { CLength *c = new CLength(100, CLengthUnit::m()); c->switchUnit(CLengthUnit::NM()); - QVERIFY2(c->getUnit() == CLengthUnit::NM() && c->getConversionSiUnit() == CLengthUnit::m(), + QVERIFY2(c->getUnit() == CLengthUnit::NM() && CLengthUnit::defaultUnit() == CLengthUnit::m(), "Testing distance units failed"); delete c; CAngle *a = new CAngle(100, CAngleUnit::rad()); a->switchUnit(CAngleUnit::deg()); - QVERIFY2(a->getUnit() == CAngleUnit::deg() && c->getConversionSiUnit() == CAngleUnit::rad(), + QVERIFY2(a->getUnit() == CAngleUnit::deg() && CAngleUnit::defaultUnit() == CAngleUnit::deg(), "Testing angle units failed"); delete a; } @@ -201,7 +208,7 @@ void CTestPhysicalQuantities::basicArithmetic() p3 /= 2.0; QVERIFY2(p3 == p1, "Pressure needs to be the same (1time)"); p3 = p3 - p3; - QVERIFY2(p3.unitValueToDouble() == 0, "Value needs to be zero"); + QVERIFY2(p3.value() == 0, "Value needs to be zero"); p3 = CPressure(1013, CPressureUnit::hPa()); QVERIFY2(p3 * 1.5 == 1.5 * p3, "Basic commutative test on PQ failed"); }