Unit tests for temperature, virtual method for value conversion

This commit is contained in:
Klaus Basan
2013-03-22 23:02:25 +01:00
parent 525910c7a3
commit 3b99954bdc
12 changed files with 136 additions and 41 deletions

View File

@@ -0,0 +1,9 @@
#ifndef BLACKCORE_H
#define BLACKCORE_H
/**
* @namespace BlackCore
* To be written
*/
#endif // BLACKCORE_H

View File

@@ -31,7 +31,8 @@ HEADERS += \
plane.h \
simulator.h \
vector_3d.h \
vector_geo.h
vector_geo.h \
blackcore.h
SOURCES += \
ecef.cpp \

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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