diff --git a/samples/physicalquantities/main.cpp b/samples/physicalquantities/main.cpp index 2fb0e2acb..ea472a4f3 100644 --- a/samples/physicalquantities/main.cpp +++ b/samples/physicalquantities/main.cpp @@ -54,7 +54,9 @@ int main(int argc, char *argv[]) CTemperature t1; CTemperature t2(20, CTemperatureUnit::C()); - qDebug() << t1 << t2; + CTemperature t3(1, CTemperatureUnit::F()); + qDebug() << t1 << t2 << t2.convertedSiValueRoundedWithUnit(); + qDebug() << t3 << t3.valueRoundedWithUnit(CTemperatureUnit::C()); // some logging wit CLogMessage bDebug << p1; diff --git a/src/blackcore/blackcore.h b/src/blackcore/blackcore.h new file mode 100644 index 000000000..5b91d074e --- /dev/null +++ b/src/blackcore/blackcore.h @@ -0,0 +1,9 @@ +#ifndef BLACKCORE_H +#define BLACKCORE_H + +/** + * @namespace BlackCore + * To be written + */ + +#endif // BLACKCORE_H diff --git a/src/blackcore/blackcore.pro b/src/blackcore/blackcore.pro index 55e4802ab..769070a17 100644 --- a/src/blackcore/blackcore.pro +++ b/src/blackcore/blackcore.pro @@ -31,7 +31,8 @@ HEADERS += \ plane.h \ simulator.h \ vector_3d.h \ - vector_geo.h + vector_geo.h \ + blackcore.h SOURCES += \ ecef.cpp \ diff --git a/src/blackmisc/pqbase.h b/src/blackmisc/pqbase.h index fc0806706..794211fa0 100644 --- a/src/blackmisc/pqbase.h +++ b/src/blackmisc/pqbase.h @@ -179,7 +179,7 @@ private: QString _type; //!< type,such as distance. Somehow redundant, but simplifies unit comparisons bool _isSIUnit; //!< is this a SI unit? bool _isSIBaseUnit; //!< SI base unit? - double _conversionFactorToSIConversionUnit; //!< factor to convert to SI + double _conversionFactorToSIConversionUnit; //!< factor to convert to SI, set to 0 if not applicable (rare cases, e.g. temperature) double _epsilon; //!< values with differences below epsilon are the equal qint32 _displayDigits; //!< standard rounding dor string conversions CMeasurementPrefix _multiplier; //!< multiplier @@ -278,7 +278,7 @@ public: * \param to * \return */ - virtual double conversionFactor(const CMeasurementUnit &to) const; + double conversionFactor(const CMeasurementUnit &to) const; /*! * \brief Factor to convert between given units * \param from diff --git a/src/blackmisc/pqphysicalquantity.cpp b/src/blackmisc/pqphysicalquantity.cpp index 60db0518d..c707d6258 100644 --- a/src/blackmisc/pqphysicalquantity.cpp +++ b/src/blackmisc/pqphysicalquantity.cpp @@ -244,14 +244,13 @@ bool CPhysicalQuantity::operator <=(const CPhysicalQuantity &otherQuantity) cons /** * Switch to another unit */ -bool CPhysicalQuantity::switchUnit(const CMeasurementUnit &unit) +bool CPhysicalQuantity::switchUnit(const CMeasurementUnit &newUnit) { - if (this->_unit == unit) return true; - if (this->_unit.getType() != unit.getType()) return false; // not possible - - double cf = this->_unit.conversionFactor(unit); - this->_unit =unit; - this->setUnitValue(cf * this->_unitValueD); + if (this->_unit == newUnit) return true; + if (this->_unit.getType() != newUnit.getType()) return false; // not possible + double cf = this->calculateValueInOtherUnit(newUnit); + this->_unit = newUnit; + this->setUnitValue(cf); return true; } @@ -275,19 +274,23 @@ void CPhysicalQuantity::setUnitValue(double baseValue) this->_unitValueI = qRound(baseValue); this->_isIntegerBaseValue = false; this->setConversionSiUnitValue(); - } /** - * @brief set SI value + * Set SI value */ void CPhysicalQuantity::setConversionSiUnitValue() { - if (this->_unit == CMeasurementUnit::None()) { - this->_convertedSiUnitValueD=0.0; - } else { - double f = this->_unit.conversionFactor(this->_conversionSiUnit); - this->_convertedSiUnitValueD =f * this->_unitValueD; - } + this->_convertedSiUnitValueD = this->calculateValueInOtherUnit(this->_conversionSiUnit); +} + +/** + * Standard conversion by factor, used in most cases,in some cases overridden (e.g.CTemperature) + */ +double CPhysicalQuantity::calculateValueInOtherUnit(const CMeasurementUnit &otherUnit) const { + if (this->_unit == CMeasurementUnit::None() || this->_unitValueD == 0.0) return 0.0; + if (this->_unit == otherUnit) return this->_unitValueD; + double f = this->_unit.conversionFactor(otherUnit); + return f * this->_unitValueD; } /** @@ -368,13 +371,8 @@ double CPhysicalQuantity::valueRounded(const CMeasurementUnit &unit, int digits) */ double CPhysicalQuantity::value(const CMeasurementUnit &unit) const { - double v; - if (unit == this->_unit) - v = this->_unitValueD; - else if (unit == this->_conversionSiUnit) - v = this->_convertedSiUnitValueD; - else - v = (this->_unit.conversionFactor(unit)) * (this->_unitValueD); + if (unit == this->_conversionSiUnit) return this->_convertedSiUnitValueD; + double v = this->calculateValueInOtherUnit(unit); return v; } diff --git a/src/blackmisc/pqphysicalquantity.h b/src/blackmisc/pqphysicalquantity.h index cddf65435..823e3a071 100644 --- a/src/blackmisc/pqphysicalquantity.h +++ b/src/blackmisc/pqphysicalquantity.h @@ -70,6 +70,14 @@ protected: * \brief Set the SI value */ void setConversionSiUnitValue(); + /*! + * Convert value in another unit, normally just by a factor, but in some cases + * (e.g. CTemperature)overridden because arbitrary conversion is required + * \sa CMeasurementUnit::conversionFactor(CMeasurementUnit) + * \param otherUnit + * \return + */ + virtual double calculateValueInOtherUnit(const CMeasurementUnit &otherUnit) const; public: /*! @@ -79,10 +87,10 @@ public: CPhysicalQuantity(const CPhysicalQuantity &otherQuantity); /*! * \brief Switch unit, e.g. feet meter - * \param unit + * \param newUnit * \return */ - bool switchUnit(const CMeasurementUnit &unit); + bool switchUnit(const CMeasurementUnit &newUnit); /*! * \brief Value in SI base unit? Meter is an SI base unit, hertz not! * \return @@ -116,7 +124,7 @@ public: * \param digits * @return */ - double valueRounded(const CMeasurementUnit &unit, int digits) const; + double valueRounded(const CMeasurementUnit &unit, int digits = -1) const; /*! * \brief Value to QString with unit, e.g. "5.00m" * \param unit @@ -143,7 +151,7 @@ public: * \brief SI value to double * @return */ - qint32 siBaseUnitValueToDouble() const { return this->_convertedSiUnitValueD;} + double siBaseUnitValueToDouble() const { return this->_convertedSiUnitValueD;} /*! * \brief Rounded value by n digits * \param digits diff --git a/src/blackmisc/pqtemperature.cpp b/src/blackmisc/pqtemperature.cpp index 1c592166c..d511435d0 100644 --- a/src/blackmisc/pqtemperature.cpp +++ b/src/blackmisc/pqtemperature.cpp @@ -7,7 +7,7 @@ namespace BlackMisc { */ CTemperature::CTemperature(): CPhysicalQuantity(0, CTemperatureUnit::K(),CTemperatureUnit::K()) { - //void + this->setUnitValue(this->unitValueToDouble()); // I have to recall, since virtual method overriding does not work in constructor } /** @@ -15,7 +15,7 @@ CTemperature::CTemperature(): CPhysicalQuantity(0, CTemperatureUnit::K(),CTemper */ CTemperature::CTemperature(const CPhysicalQuantity &temperature): CPhysicalQuantity(temperature) { - //void + this->setUnitValue(this->unitValueToDouble()); // I have to recall, since virtual method overriding does not work in constructor } /** @@ -23,7 +23,7 @@ CTemperature::CTemperature(const CPhysicalQuantity &temperature): CPhysicalQuant */ CTemperature::CTemperature(qint32 value, const CTemperatureUnit &unit) : CPhysicalQuantity(value, unit, CTemperatureUnit::K()) { - // void + this->setUnitValue(value); // I have to recall, since virtual method overriding does not work in constructor } /** @@ -31,7 +31,41 @@ CTemperature::CTemperature(qint32 value, const CTemperatureUnit &unit) : CPhysic */ CTemperature::CTemperature(double value, const CTemperatureUnit &unit) : CPhysicalQuantity(value, unit, CTemperatureUnit::K()) { - // void + this->setUnitValue(value); // I have to recall, since virtual method overriding does not work in constructor +} + +/** + * Overriden specializedmethodfortemperture + */ +double CTemperature::calculateValueInOtherUnit(const CMeasurementUnit &otherUnit) const +{ + if (this->getUnit()==otherUnit) return this->siBaseUnitValueToDouble(); + + double siValue; + // I always convert via SI Unit, other I would need too many conversions + if(otherUnit == this->_conversionSiUnit) { + // here I expect a conversion to SI is required and not done yet + if(this->_unit == CTemperatureUnit::C()) { + siValue = this->unitValueToDouble() + 273.15; + } else if(this->_unit == CTemperatureUnit::F()) { + siValue = (this->unitValueToDouble() + 459.67) *5.0 / 9.0; + } else{ + // TODO: EXCEPTION + } + } else { + // here I expect the SI value is already set + siValue = this->siBaseUnitValueToDouble(); + } + + // from SI + if (otherUnit == this->_conversionSiUnit) return siValue; + if(otherUnit == CTemperatureUnit::C()) { + return siValue - 273.15; + } else if(this->_unit == CTemperatureUnit::F()) { + return (siValue * 9.0 / 5.0) - 459.67; + } + // TODO: Exception + return 0; } } // namespace BlackCore diff --git a/src/blackmisc/pqtemperature.h b/src/blackmisc/pqtemperature.h index f1b144eaf..32530edc1 100644 --- a/src/blackmisc/pqtemperature.h +++ b/src/blackmisc/pqtemperature.h @@ -30,15 +30,20 @@ public: */ CTemperatureUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {} /*! - * \brief Meter m + * \brief Kelvin * \return */ static CTemperatureUnit& K() { static CTemperatureUnit K("Kelvin", "K", true, true); return K;} /*! - * \brief Nautical miles NM + * \brief Centigrade C * \return */ static CTemperatureUnit& C() { static CTemperatureUnit C("centigrade", "°C", false, false);return C;} + /*! + * \brief Fahrenheit F + * \return + */ + static CTemperatureUnit& F() { static CTemperatureUnit F("Fahrenheit", "°F", false, false, 5.0/9.0);return F;} }; /*! @@ -47,6 +52,14 @@ public: */ class CTemperature : public CPhysicalQuantity { +protected: + /*! + * Specific method for temperature, a normal factor conversion is not sufficient. + * \param otherUnit + * \return + */ + virtual double calculateValueInOtherUnit(const CMeasurementUnit &otherUnit) const; + public: /*! * \brief Default constructor diff --git a/tests/blackmisc/blackmisctest.h b/tests/blackmisc/blackmisctest.h new file mode 100644 index 000000000..580552dc6 --- /dev/null +++ b/tests/blackmisc/blackmisctest.h @@ -0,0 +1,11 @@ +#ifndef BLACKMISCTEST_H +#define BLACKMISCTEST_H + +/** + * @namespace BlackMiscTest + * Unit test for BlackMisc. Unit test do have their own namespace, so + * the regular namespace BlackMiscis completely free of unit tests. + * Add any new tests to TestMain::unitMain as shown there in the pattern. + */ + +#endif // BLACKMISCTEST_H diff --git a/tests/blackmisc/test_blackmisc.pro b/tests/blackmisc/test_blackmisc.pro index 7a6335fa7..21f3a453a 100644 --- a/tests/blackmisc/test_blackmisc.pro +++ b/tests/blackmisc/test_blackmisc.pro @@ -10,7 +10,8 @@ CONFIG -= app_bundle DEPENDPATH += . ../../src INCLUDEPATH += . ../../src SOURCES += main.cpp testmain.cpp testphysicalquantitiesbase.cpp -HEADERS += testmain.h testphysicalquantitiesbase.h +HEADERS += testmain.h testphysicalquantitiesbase.h \ + blackmisctest.h win32-msvc* { PRE_TARGETDEPS += ../../lib/blackmisc.lib diff --git a/tests/blackmisc/testphysicalquantitiesbase.cpp b/tests/blackmisc/testphysicalquantitiesbase.cpp index 5d260ce91..debce3356 100644 --- a/tests/blackmisc/testphysicalquantitiesbase.cpp +++ b/tests/blackmisc/testphysicalquantitiesbase.cpp @@ -70,8 +70,8 @@ void TestPhysicalQuantitiesBase::speedBasics() { CSpeed s1(100, CSpeedUnit::km_h()); CSpeed s2(1000, CSpeedUnit::ft_min()); - QVERIFY2(s1.valueRounded(CSpeedUnit::NM_h(),0) == 54, "100km/h is 54NM/h"); - QVERIFY2(s2.valueRounded(CSpeedUnit::m_s(),1) == 5.1, "1000ft/min is 5.1m/s"); + QVERIFY2(s1.valueRounded(CSpeedUnit::NM_h(),0) == 54, qPrintable(QString("100km/h is not %1 NM/h").arg(s1.valueRounded(CSpeedUnit::NM_h(),0)))); + QVERIFY2(s2.valueRounded(CSpeedUnit::m_s(),1) == 5.1, qPrintable(QString("1000ft/min is not %1 m/s").arg(s2.valueRounded(CSpeedUnit::m_s(),1)))); } /** @@ -94,8 +94,8 @@ void TestPhysicalQuantitiesBase::angleTests() CAngle a1(180, CAngleUnit::deg()); CAngle a2(1.5 * CAngle::pi()); a2.switchUnit(CAngleUnit::deg()); - QVERIFY2(a2.unitValueToInteger() == 270, "1.5Pi should be 270deg"); - QVERIFY2(a1.piFactor() == 1, "Pi should be 180deg"); + QVERIFY2(a2.unitValueToInteger() == 270, qPrintable(QString("1.5Pi should be 270deg, not %1 deg").arg(a2.unitValueToInteger()))); + QVERIFY2(a1.piFactor() == 1, qPrintable(QString("Pi should be 1PI,not %1").arg(a1.piFactor()))); } /** @@ -129,6 +129,20 @@ void TestPhysicalQuantitiesBase::pressureTests() QVERIFY2(p1.unitValueToDouble() == p4.unitValueToDouble(), "mbar/hPa test"); } +/** + * Temperature tests + */ +void TestPhysicalQuantitiesBase::temperatureTests() +{ + CTemperature t1(0, CTemperatureUnit::C()); // 0C + CTemperature t2(1, CTemperatureUnit::F()); // 1F + CTemperature t3(220.15, CTemperatureUnit::F()); + QVERIFY2(t1.convertedSiValueToDoubleRounded() == 273.15, qPrintable(QString("0C shall be 273.15K, not %1 K").arg(t1.convertedSiValueToDoubleRounded()))); + 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())))); + +} + /** * @brief Just tesing obvious memory create / destruct flaws */ diff --git a/tests/blackmisc/testphysicalquantitiesbase.h b/tests/blackmisc/testphysicalquantitiesbase.h index efb8951ec..09e6cbd65 100644 --- a/tests/blackmisc/testphysicalquantitiesbase.h +++ b/tests/blackmisc/testphysicalquantitiesbase.h @@ -48,6 +48,10 @@ private slots: * \brief Testing pressure */ void pressureTests(); + /*! + * \brief Testing temperature + */ + void temperatureTests(); /*! * \brief testing construction / destruction in memory */