Changed PQ to template, removed unit default values, checked unit tests

This commit is contained in:
Klaus Basan
2013-03-27 12:03:16 +01:00
parent b3439ea3e4
commit 5677cd41e3
23 changed files with 408 additions and 1091 deletions

View File

@@ -15,20 +15,30 @@ using namespace BlackMisc;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// cases which must not work
// CMeasurementUnit mu; //must not work
// CDistanceUnit du1(CAngleUnit::rad());
CDistanceUnit du2(CDistanceUnit::cm());
CDistanceUnit du3(CDistanceUnit::ft());
const CDistance d1(5.0, CDistanceUnit::ft()); // 5 ft
CDistance d2(1, CDistanceUnit::NM()); // 1NM
CDistance d3(1, CDistanceUnit::km());
qDebug() << d1 << d2 << d3;
CDistance d4(d3);
qDebug() << CDistanceUnit::ft();
qDebug() << d1 << d2 << d3 << d4;
qDebug() << d1.valueRoundedWithUnit(CDistanceUnit::ft(),5)
<< d2.valueRoundedWithUnit(CDistanceUnit::km());
qDebug() << d3.getUnit();
d2.switchUnit(CDistanceUnit::ft()); // now in ft
d3 += d3; // 2km now
d3 *= 1.5;// 3km now
qDebug() << d2 << d3;
CFrequency f1(1E6); // 1MHz
CFrequency f1(1E6, CFrequencyUnit::Hz()); // 1MHz
qDebug() << f1 << f1.valueRoundedWithUnit(CFrequencyUnit::MHz()) << f1.valueRoundedWithUnit(CFrequencyUnit::GHz(), 3);
CSpeed s1 = CSpeed(100, CSpeedUnit::km_h());
@@ -39,7 +49,14 @@ int main(int argc, char *argv[])
qDebug() << s2 << s3;
CAngle a1(180, CAngleUnit::deg());
CAngle a2(1.5 * CAngle::pi());
CAngle a2(1.5 * CAngle::pi(), CAngleUnit::rad());
a1 += a2;
// a1 = d2; // must not work
qDebug() << a1;
a1.switchUnit(CAngleUnit::deg());
// a2 += d1; // must not work
a2 = a1 + a1;
a2.switchUnit(CAngleUnit::deg());
qDebug() << a1.unitValueRoundedWithUnit() << a1.piFactor();
qDebug() << a2;
@@ -65,6 +82,7 @@ int main(int argc, char *argv[])
// some of the faults Mathew has pointed out,not longer possible
// CAngleUnit::rad() = CAngleUnit::deg();
// qDebug() << CAngleUnit::rad(); // wrong
(t1 - t2).switchUnit(CTemperatureUnit::F()); // was not working since wrong return type const
// CDistanceUnit duA(CSpeedUnit::ft_min()); // no longer possible
CDistanceUnit duB(CDistanceUnit::cm());

View File

@@ -45,7 +45,10 @@ HEADERS += \
pqmass.h \
pqpressure.h \
pqtemperature.h \
pqconstants.h
pqconstants.h \
avverticalposition.h \
pqunits.h \
pqallquantities.h
SOURCES += \
logmessage.cpp \
@@ -66,15 +69,9 @@ SOURCES += \
type_info.cpp \
message_dispatcher.cpp \
message_system.cpp \
pqdistance.cpp \
pqphysicalquantity.cpp \
pqfrequency.cpp \
pqbase.cpp \
pqspeed.cpp \
pqangle.cpp \
pqmass.cpp \
pqpressure.cpp \
pqtemperature.cpp \
pqconstants.cpp
avverticalposition.cpp
DESTDIR = ../../lib

View File

@@ -1,45 +0,0 @@
#include "blackmisc/pqangle.h"
namespace BlackMisc {
/**
* Default constructor
*/
CAngle::CAngle() : CPhysicalQuantity(0, CAngleUnit::rad(), CAngleUnit::rad())
{
// void
}
/**
* Constructor
*/
CAngle::CAngle(const CPhysicalQuantity &angle): CPhysicalQuantity(angle)
{
//void
}
/**
* Constructor
*/
CAngle::CAngle(qint32 value, const CAngleUnit &unit) : CPhysicalQuantity(value, unit, CAngleUnit::rad())
{
// void
}
/**
* Constructor
*/
CAngle::CAngle(double value, const CAngleUnit &unit) : CPhysicalQuantity(value, unit, CAngleUnit::rad())
{
// void
}
/**
* Destructor
*/
CAngle::~CAngle()
{
// void
}
} // namespace

View File

@@ -1,89 +1,41 @@
#ifndef PQANGLE_H
#define PQANGLE_H
#include "pqphysicalquantity.h"
#include "math.h"
#include "blackmisc/pqphysicalquantity.h"
namespace BlackMisc {
/*!
* Specialized class for angles (degrees, radian).
* \author KWB
*/
class CAngleUnit : public CMeasurementUnit {
friend class CAngle;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CAngleUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief Angle units: Radian, degree
* \param name
* \param unitName
* \param isSIUnit
* \param conversionFactorToSI
* \param mulitplier
* \param displayDigits
* \param epsilon
*/
CAngleUnit(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, "angle", isSIUnit, false, conversionFactorToSI, mulitplier, displayDigits, epsilon) {}
/*!
* \brief Meter m
* \return
*/
static const CAngleUnit& rad() { static CAngleUnit rad("radian", "rad", true); return rad;}
/*!
* \brief Nautical miles NM
* \return
*/
static const CAngleUnit& deg() { static CAngleUnit deg("degree", "°", false, M_PI/180); return deg;}
};
/*!
* \brief Physical unit degree
* \author KWB
*/
class CAngle : public CPhysicalQuantity
class CAngle : public CPhysicalQuantity<CAngleUnit, CAngle>
{
public:
/*!
* \brief Default constructor
*/
CAngle();
CAngle() : CPhysicalQuantity(0, CAngleUnit::rad(), CAngleUnit::rad()) {}
/**
*\brief downcast copy constructor
*/
CAngle(const CPhysicalQuantity &angle);
* \brief Copy constructor
*/
CAngle(const CAngle &angle) : CPhysicalQuantity(angle) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CAngle(qint32 value, const CAngleUnit &unit = CAngleUnit::rad());
CAngle(qint32 value, const CAngleUnit &unit): CPhysicalQuantity(value, unit, CAngleUnit::rad()) {}
/*!
*\brief Init by double value
* \brief Init by double value
* \param value
* \param unit
*/
CAngle(double value, const CAngleUnit &unit = CAngleUnit::rad());
CAngle(double value, const CAngleUnit &unit): CPhysicalQuantity(value, unit, CAngleUnit::rad()) {}
/*!
* \brief Virtual destructor
*/
virtual ~CAngle();
/*!
* \brief Unit of the distance
* \return
*/
CAngleUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CAngleUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CAngle() {}
/*!
* \brief Convenience method PI
* \return
@@ -94,8 +46,8 @@ public:
* \return
*/
double piFactor() const { return CPhysicalQuantity::round(this->convertedSiValueToDouble() / M_PI,6);}
};
} // namespace blackCore
} // namespace
#endif // PQANGLE_H

View File

@@ -198,8 +198,6 @@ protected:
* \param epsilon
*/
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);
public:
/*!
* \brief Copy constructor
* \param otherUnit
@@ -211,6 +209,8 @@ public:
* \return
*/
CMeasurementUnit &operator =(const CMeasurementUnit &otherUnit);
public:
/*!
* \brief Equal operator ==
* \param otherUnit

View File

@@ -1,7 +0,0 @@
#include "blackmisc/pqconstants.h"
namespace BlackMisc {
// no code here, all in header
} // namespace

View File

@@ -1,19 +1,13 @@
#ifndef PQCONSTANTS_H
#define PQCONSTANTS_H
#include "blackmisc/blackmisc.h"
#include "blackmisc/pqdistance.h"
#include "blackmisc/pqfrequency.h"
#include "blackmisc/pqspeed.h"
#include "blackmisc/pqangle.h"
#include "blackmisc/pqmass.h"
#include "blackmisc/pqpressure.h"
#include "blackmisc/pqtemperature.h"
#include "blackmisc/pqallquantities.h"
namespace BlackMisc{
class CPhysicalQuantitiesConstants
{
public:
/*!
* \brief Temperature absolute Zero in °C

View File

@@ -1,45 +0,0 @@
#include "blackmisc/pqdistance.h"
namespace BlackMisc {
/**
* Default Constructor
*/
CDistance::CDistance(): CPhysicalQuantity(0, CDistanceUnit::m(),CDistanceUnit::m())
{
//void
}
/**
* Constructor
*/
CDistance::CDistance(const CPhysicalQuantity &distance): CPhysicalQuantity(distance)
{
//void
}
/**
* Constructor
*/
CDistance::CDistance(qint32 value, const CDistanceUnit &unit) : CPhysicalQuantity(value, unit, CDistanceUnit::m())
{
// void
}
/**
* Constructor
*/
CDistance::CDistance(double value, const CDistanceUnit &unit) : CPhysicalQuantity(value, unit, CDistanceUnit::m())
{
// void
}
/**
* Destructor
*/
CDistance::~CDistance()
{
// void
}
} // namespace BlackCore

View File

@@ -1,104 +1,40 @@
#ifndef PQDISTANCE_H
#define PQDISTANCE_H
#include "pqphysicalquantity.h"
#include "blackmisc/pqphysicalquantity.h"
namespace BlackMisc {
/*!
* Specialized class for distance units (meter, foot, nautical miles).
* \author KWB
*/
class CDistanceUnit : public CMeasurementUnit {
friend class CDistance;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CDistanceUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief Distance unit
* \param name
* \param unitName
* \param isSIUnit
* \param isSIBaseUnit
* \param conversionFactorToSI
* \param mulitplier
* \param displayDigits
* \param epsilon
*/
CDistanceUnit(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) {}
/*!
* \brief Meter m
* \return
*/
static const CDistanceUnit& m() { static CDistanceUnit m("meter", "m", true, true); return m;}
/*!
* \brief Nautical miles NM
* \return
*/
static const CDistanceUnit& NM() { static CDistanceUnit NM("nautical miles", "NM", false, false, 1000.0*1.85200, CMeasurementPrefix::One(), 3);return NM;}
/*!
* \brief Foot ft
* \return
*/
static const CDistanceUnit& ft() { static CDistanceUnit ft("foot", "ft", false, false, 0.3048, CMeasurementPrefix::One(), 0); return ft;}
/*!
* \brief Kilometer km
* \return
*/
static const CDistanceUnit& km() { static CDistanceUnit km("kilometer", "km", true, false, CMeasurementPrefix::k().getFactor(), CMeasurementPrefix::k(), 3);return km;}
/*!
* \brief Centimeter cm
* \return
*/
static const CDistanceUnit& cm() { static CDistanceUnit cm("centimeter", "cm", true, false, CMeasurementPrefix::c().getFactor(), CMeasurementPrefix::c(), 1);return cm;}
};
/*!
* \brief Physical unit distance
* \author KWB
*/
class CDistance : public CPhysicalQuantity
class CDistance : public CPhysicalQuantity<CDistanceUnit,CDistance>
{
public:
/*!
* \brief Default constructor
*/
CDistance();
CDistance() : CPhysicalQuantity (0, CDistanceUnit::m(), CDistanceUnit::m()) {}
/**
*\brief downcast copy constructor
*\brief Copy constructor
*/
CDistance(const CPhysicalQuantity &distance);
CDistance(const CDistance &distance) : CPhysicalQuantity(distance) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CDistance(qint32 value, const CDistanceUnit &unit = CDistanceUnit::m());
CDistance(qint32 value, const CDistanceUnit &unit) : CPhysicalQuantity(value, unit, CDistanceUnit::m()) {}
/*!
*\brief Init by double value
* \param value
* \param unit
*/
CDistance(double value, const CDistanceUnit &unit = CDistanceUnit::m());
CDistance(double value, const CDistanceUnit &unit) : CPhysicalQuantity(value, unit, CDistanceUnit::m()) {}
/*!
* \brief Virtual destructor
*/
virtual ~CDistance();
/*!
* \brief Unit of the distance
* \return
*/
CDistanceUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CDistanceUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CDistance() {}
};
} // namespace blackCore
} // namespace
#endif // PQDISTANCE_H

View File

@@ -1,46 +0,0 @@
#include "blackmisc/pqfrequency.h"
namespace BlackMisc {
/**
* Default constructor
*/
CFrequency::CFrequency() : CPhysicalQuantity(0, CFrequencyUnit::Hz(), CFrequencyUnit::Hz())
{
// void
}
/**
* Constructor
*/
CFrequency::CFrequency(const CPhysicalQuantity &frequency): CPhysicalQuantity(frequency)
{
//void
}
/**
* Constructor
*/
CFrequency::CFrequency(qint32 value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit, CFrequencyUnit::Hz())
{
// void
}
/**
* Constructor
*/
CFrequency::CFrequency(double value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit, CFrequencyUnit::Hz())
{
// void
}
/**
* Destructor
*/
CFrequency::~CFrequency()
{
// void
}
} // namespace

View File

@@ -4,95 +4,37 @@
namespace BlackMisc {
/*!
* Specialized class for frequency (hertz, mega hertz, kilo hertz).
* \author KWB
*/
class CFrequencyUnit : public CMeasurementUnit {
friend class CFrequency;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CFrequencyUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief CFrequencyUnit
* \param name
* \param unitName
* \param isSIUnit
* \param conversionFactorToSI
* \param mulitplier
* \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) {}
/*!
* \brief Hertz
* \return
*/
static const CFrequencyUnit& Hz() { static CFrequencyUnit Hz("hertz", "Hz", true); return Hz;}
/*!
* \brief Kilohertz
* \return
*/
static const CFrequencyUnit& kHz() { static CFrequencyUnit kHz("kilohertz", "kHz", true, CMeasurementPrefix::k().getFactor(), CMeasurementPrefix::k(), 0);return kHz;}
/*!
* \brief Megahertz
* \return
*/
static const CFrequencyUnit& MHz() { static CFrequencyUnit MHz("megahertz", "MHz", false, CMeasurementPrefix::M().getFactor(), CMeasurementPrefix::M(), 0); return MHz;}
/*!
* \brief Gigahertz
* \return
*/
static const CFrequencyUnit& GHz() { static CFrequencyUnit GHz("gigahertz", "GHz", true, CMeasurementPrefix::G().getFactor(), CMeasurementPrefix::G(), 0);return GHz;}
};
/*!
* \brief Physical unit distance
* \author KWB
*/
class CFrequency : public CPhysicalQuantity
class CFrequency : public CPhysicalQuantity<CFrequencyUnit,CFrequency>
{
public:
/*!
* \brief Default constructor
*/
CFrequency();
CFrequency() : CPhysicalQuantity(0, CFrequencyUnit::Hz(), CFrequencyUnit::Hz()) {}
/**
*\brief downcast copy constructor
*\brief Copy constructor
*/
CFrequency(const CPhysicalQuantity &frequency);
CFrequency(const CFrequency &frequency) : CPhysicalQuantity(frequency) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CFrequency(qint32 value, const CFrequencyUnit &unit = CFrequencyUnit::Hz());
CFrequency(qint32 value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit, CFrequencyUnit::Hz()){}
/*!
* \brief Init by double value
* \param value
* \param unit
*/
CFrequency(double value, const CFrequencyUnit &unit = CFrequencyUnit::Hz());
CFrequency(double value, const CFrequencyUnit &unit) : CPhysicalQuantity(value, unit, CFrequencyUnit::Hz()){}
/*!
* \brief Virtual destructor
*/
virtual ~CFrequency();
/*!
* \brief Unit of the distance
* \return
*/
CFrequencyUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CFrequencyUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CFrequency() {}
};
} // namespace blackCore
} // namespace
#endif // PQFREQUENCY_H

View File

@@ -1,45 +0,0 @@
#include "blackmisc/pqmass.h"
namespace BlackMisc {
/**
* Default Constructor
*/
CMass::CMass(): CPhysicalQuantity(0, CMassUnit::kg(),CMassUnit::kg())
{
// void
}
/**
* Constructor
*/
CMass::CMass(const CPhysicalQuantity &mass): CPhysicalQuantity(mass)
{
// void
}
/**
* Constructor
*/
CMass::CMass(qint32 value, const CMassUnit &unit) : CPhysicalQuantity(value, unit, CMassUnit::kg())
{
// void
}
/**
* Constructor
*/
CMass::CMass(double value, const CMassUnit &unit) : CPhysicalQuantity(value, unit, CMassUnit::kg())
{
// void
}
/**
* Destructor
*/
CMass::~CMass()
{
// void
}
} // namespace BlackMisc

View File

@@ -4,98 +4,39 @@
namespace BlackMisc {
/*!
* Specialized class for mass units (kg, lbs).
* \author KWB
*/
class CMassUnit : public CMeasurementUnit {
friend class CMass;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CMassUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief Mass units
* \param name
* \param unitName
* \param isSIUnit
* \param isSIBaseUnit
* \param conversionFactorToSI
* \param mulitplier
* \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) {}
/*!
* \brief Kilogram, SI base unit
* \return
*/
static const CMassUnit& kg() { static CMassUnit kg("kilogram", "kg", true, true, 1.0, CMeasurementPrefix::k(), 1); return kg;}
/*!
* \brief Gram, SI unit
* \return
*/
static const CMassUnit& g() { static CMassUnit g("gram", "g", true, false, 1.0/1000.0, CMeasurementPrefix::One(), 0); return g;}
/*!
* \brief Tonne, aka metric tonne (1000kg)
* \return
*/
static const CMassUnit& t() { static CMassUnit t("tonne", "t", true, false, 1000.0, CMeasurementPrefix::One(), 3); return t;}
/*!
* \brief Pound, aka mass pound
* \return
*/
static const CMassUnit& lb() { static CMassUnit lbs("pound", "lb", false, false, 0.45359237, CMeasurementPrefix::One(), 1); return lbs;}
};
/*!
* \brief Mass
* \author KWB
*/
class CMass : public CPhysicalQuantity
class CMass : public CPhysicalQuantity<CMassUnit,CMass>
{
public:
/*!
* \brief Default constructor
*/
CMass();
CMass() : CPhysicalQuantity(0, CMassUnit::kg(), CMassUnit::kg()) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CMass(qint32 value, const CMassUnit &unit = CMassUnit::kg());
CMass(qint32 value, const CMassUnit &unit) : CPhysicalQuantity(value, unit, CMassUnit::kg()){}
/*!
*\brief Init by double value
* \brief Init by double value
* \param value
* \param unit
*/
CMass(double value, const CMassUnit &unit = CMassUnit::kg());
CMass(double value, const CMassUnit &unit) : CPhysicalQuantity(value, unit, CMassUnit::kg()){}
/*!
* \brief Copyconstructor
* \brief Copy constructor
* \param mass
*/
CMass(const CPhysicalQuantity &mass);
CMass(const CPhysicalQuantity &mass) : CPhysicalQuantity(mass){}
/*!
* \brief Virtual destructor
*/
virtual ~CMass();
/*!
* \brief Unit of the mass
* \return
*/
CMassUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CMassUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CMass() {}
};
} // namespace blackCore
} // namespace
#endif // PQMASS_H

View File

@@ -1,12 +1,12 @@
#include "blackmisc/pqphysicalquantity.h"
#include "blackmisc/pqallquantities.h"
namespace BlackMisc {
/**
* Constructor by integer
*/
CPhysicalQuantity::CPhysicalQuantity(qint32 baseValue, const CMeasurementUnit &unit, const CMeasurementUnit &siConversionUnit, const CPhysicalQuantityUnitConverter unitConverter) :
_pUnit(unit), _pConversionSiUnit(siConversionUnit), _unitConverter(unitConverter)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ>::CPhysicalQuantity(qint32 baseValue, const MU &unit, const MU &siConversionUnit, const CPhysicalQuantityUnitConverter unitConverter) :
m_unit(unit), m_conversionSiUnit(siConversionUnit), m_unitConverter(unitConverter)
{
this->setUnitValue(baseValue);
}
@@ -14,8 +14,8 @@ CPhysicalQuantity::CPhysicalQuantity(qint32 baseValue, const CMeasurementUnit &u
/**
* Constructor by double
*/
CPhysicalQuantity::CPhysicalQuantity(double baseValue, const CMeasurementUnit &unit, const CMeasurementUnit &siConversionUnit, const CPhysicalQuantityUnitConverter unitConverter) :
_pUnit(unit), _pConversionSiUnit(siConversionUnit),_unitConverter(unitConverter)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ>::CPhysicalQuantity(double baseValue, const MU &unit, const MU &siConversionUnit, const CPhysicalQuantityUnitConverter unitConverter) :
m_unit(unit), m_conversionSiUnit(siConversionUnit),m_unitConverter(unitConverter)
{
this->setUnitValue(baseValue);
}
@@ -23,9 +23,9 @@ CPhysicalQuantity::CPhysicalQuantity(double baseValue, const CMeasurementUnit &u
/**
* Copy constructor
*/
CPhysicalQuantity::CPhysicalQuantity(const CPhysicalQuantity &otherQuantity) :
_unitValueD(otherQuantity._unitValueD), _unitValueI(otherQuantity._unitValueI), _convertedSiUnitValueD(otherQuantity._convertedSiUnitValueD),
_isIntegerBaseValue(otherQuantity._isIntegerBaseValue), _pUnit(otherQuantity._pUnit), _pConversionSiUnit(otherQuantity._pConversionSiUnit), _unitConverter(otherQuantity._unitConverter)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ>::CPhysicalQuantity(const CPhysicalQuantity &otherQuantity) :
m_unitValueD(otherQuantity.m_unitValueD), m_unitValueI(otherQuantity.m_unitValueI), m_convertedSiUnitValueD(otherQuantity.m_convertedSiUnitValueD),
m_isIntegerBaseValue(otherQuantity.m_isIntegerBaseValue), m_unit(otherQuantity.m_unit), m_conversionSiUnit(otherQuantity.m_conversionSiUnit), m_unitConverter(otherQuantity.m_unitConverter)
{
// void
}
@@ -33,62 +33,42 @@ CPhysicalQuantity::CPhysicalQuantity(const CPhysicalQuantity &otherQuantity) :
/*!
* Destructor
*/
CPhysicalQuantity::~CPhysicalQuantity()
template <class MU, class PQ> CPhysicalQuantity<MU,PQ>::~CPhysicalQuantity()
{
// void
}
/**
* Stream operator
*/
QDebug operator <<(QDebug d, const CPhysicalQuantity &quantity)
{
QString v = quantity.unitValueRoundedWithUnit(-1);
d << v;
return d;
}
/**
* Stream operator
*/
CLogMessage operator <<(CLogMessage d, const CPhysicalQuantity &quantity)
{
QString v = quantity.unitValueRoundedWithUnit(-1);
d << v;
return d;
}
/**
* Equal operator ==
*/
bool CPhysicalQuantity::operator ==(const CPhysicalQuantity &otherQuantity) const
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator ==(const CPhysicalQuantity<MU,PQ> &otherQuantity) const
{
if(this == &otherQuantity) return true;
if(this->_pUnit.getType()!= otherQuantity._pUnit.getType()) return false;
if(this->m_unit.getType()!= otherQuantity.m_unit.getType()) return false;
// some special case for best quality
double diff;
const double lenient = 1.001; // even diff alread has a round issue
if (this->_pUnit == otherQuantity._pUnit) {
const double lenient = 1.001; // even diff already has a rounding issue to be avoided
if (this->m_unit == otherQuantity.m_unit) {
// same unit
if (this->_isIntegerBaseValue && otherQuantity._isIntegerBaseValue) {
if (this->m_isIntegerBaseValue && otherQuantity.m_isIntegerBaseValue) {
// pure integer comparison, no rounding issues
return this->_unitValueI == otherQuantity._unitValueI;
return this->m_unitValueI == otherQuantity.m_unitValueI;
} else {
diff = abs(this->_unitValueD - otherQuantity._unitValueD);
return diff <= (lenient * this->_pUnit.getEpsilon());
diff = abs(this->m_unitValueD - otherQuantity.m_unitValueD);
return diff <= (lenient * this->m_unit.getEpsilon());
}
} else {
// based on SI value
diff = abs(this->_convertedSiUnitValueD - otherQuantity._convertedSiUnitValueD);
return diff <= (lenient * this->_pUnit.getEpsilon());
diff = abs(this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD);
return diff <= (lenient * this->m_unit.getEpsilon());
}
}
/**
* Not equal
*/
bool CPhysicalQuantity::operator !=(const CPhysicalQuantity &otherQuantity) const {
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator !=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const {
if(this == &otherQuantity) return false;
return !(*this == otherQuantity);
}
@@ -96,37 +76,37 @@ bool CPhysicalQuantity::operator !=(const CPhysicalQuantity &otherQuantity) cons
/**
* Assigment operator =
*/
CPhysicalQuantity& CPhysicalQuantity::operator=(const CPhysicalQuantity &otherQuantity) {
template <class MU, class PQ> CPhysicalQuantity<MU,PQ>& CPhysicalQuantity<MU,PQ>::operator=(const CPhysicalQuantity<MU,PQ> &otherQuantity) {
// Check for self-assignment!
if (this == &otherQuantity) return *this; // Same object? Yes, so skip assignment, and just return *this
CPhysicalQuantity::_unitValueI = otherQuantity._unitValueI;
CPhysicalQuantity::_unitValueD = otherQuantity._unitValueD;
CPhysicalQuantity::_convertedSiUnitValueD = otherQuantity._convertedSiUnitValueD;
CPhysicalQuantity::_isIntegerBaseValue = otherQuantity._isIntegerBaseValue;
CPhysicalQuantity::_pUnit = otherQuantity._pUnit;
CPhysicalQuantity::_pConversionSiUnit = otherQuantity._pConversionSiUnit;
CPhysicalQuantity::_unitConverter = otherQuantity._unitConverter;
this->m_unitValueI = otherQuantity.m_unitValueI;
this->m_unitValueD = otherQuantity.m_unitValueD;
this->m_convertedSiUnitValueD = otherQuantity.m_convertedSiUnitValueD;
this->m_isIntegerBaseValue = otherQuantity.m_isIntegerBaseValue;
this->m_unit = otherQuantity.m_unit;
this->m_conversionSiUnit = otherQuantity.m_conversionSiUnit;
this->m_unitConverter = otherQuantity.m_unitConverter;
return *this;
}
/**
* Plus operator
*/
CPhysicalQuantity &CPhysicalQuantity::operator +=(const CPhysicalQuantity &otherQuantity)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ> &CPhysicalQuantity<MU,PQ>::operator +=(const CPhysicalQuantity<MU,PQ> &otherQuantity)
{
if (this->_pUnit == otherQuantity._pUnit) {
if (this->m_unit == otherQuantity.m_unit) {
// same unit
if (this->_isIntegerBaseValue && otherQuantity._isIntegerBaseValue) {
if (this->m_isIntegerBaseValue && otherQuantity.m_isIntegerBaseValue) {
// pure integer, no rounding issues
this->setUnitValue(otherQuantity._unitValueI + this->_unitValueI);
this->setUnitValue(otherQuantity.m_unitValueI + this->m_unitValueI);
} else {
this->setUnitValue(otherQuantity._unitValueI + this->_unitValueI);
this->setUnitValue(otherQuantity.m_unitValueD + this->m_unitValueD);
}
} else {
double v = otherQuantity.value(this->_pUnit);
this->setUnitValue(v + this->_unitValueD);
double v = otherQuantity.value(this->m_unit);
this->setUnitValue(v + this->m_unitValueD);
}
return *this;
}
@@ -134,40 +114,46 @@ CPhysicalQuantity &CPhysicalQuantity::operator +=(const CPhysicalQuantity &other
/**
* Plus operator
*/
CPhysicalQuantity &CPhysicalQuantity::operator +=(double unprefixedSiUnitValue)
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator +(const PQ &otherQuantity) const
{
if (!this->isUnprefixedSiUnit()) {
this->switchUnit(this->_pConversionSiUnit);
}
this->setUnitValue(this->_unitValueD + unprefixedSiUnitValue);
return *this;
PQ plus(otherQuantity);
plus += (*this);
return plus;
}
/**
* Explicit plus
*/
template <class MU, class PQ> void CPhysicalQuantity<MU,PQ>::addUnitValue(double value)
{
this->setUnitValue(this->m_unitValueD + value);
}
/**
* Plus operator
* Explicit minus
*/
CPhysicalQuantity CPhysicalQuantity::operator +(const CPhysicalQuantity &otherQuantity) const
template <class MU, class PQ> void CPhysicalQuantity<MU,PQ>::substractUnitValue(double value)
{
CPhysicalQuantity pq = (*this);
return pq+= otherQuantity;
this->setUnitValue(this->m_unitValueD - value);
}
/**
* Minus operator
*/
CPhysicalQuantity &CPhysicalQuantity::operator -=(const CPhysicalQuantity &otherQuantity)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ> &CPhysicalQuantity<MU,PQ>::operator -=(const CPhysicalQuantity<MU,PQ> &otherQuantity)
{
if (this->_pUnit == otherQuantity._pUnit) {
if (this->m_unit == otherQuantity.m_unit) {
// same unit
if (this->_isIntegerBaseValue && otherQuantity._isIntegerBaseValue) {
if (this->m_isIntegerBaseValue && otherQuantity.m_isIntegerBaseValue) {
// pure integer, no rounding issues
this->setUnitValue(otherQuantity._unitValueI - this->_unitValueI);
this->setUnitValue(otherQuantity.m_unitValueI - this->m_unitValueI);
} else {
this->setUnitValue(otherQuantity._unitValueI - this->_unitValueI);
this->setUnitValue(otherQuantity.m_unitValueD - this->m_unitValueD);
}
} else {
double v = otherQuantity.value(this->_pUnit);
this->setUnitValue(v - this->_unitValueD);
double v = otherQuantity.value(this->m_unit);
this->setUnitValue(v - this->m_unitValueD);
}
return *this;
}
@@ -175,77 +161,83 @@ CPhysicalQuantity &CPhysicalQuantity::operator -=(const CPhysicalQuantity &other
/**
* Minus operator
*/
CPhysicalQuantity &CPhysicalQuantity::operator -=(double unprefixedSiUnitValue)
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator -(const PQ &otherQuantity) const
{
*this += (-unprefixedSiUnitValue);
return *this;
}
/**
* Minus operator
*/
CPhysicalQuantity CPhysicalQuantity::operator -(const CPhysicalQuantity &otherQuantity) const
{
CPhysicalQuantity pq = (*this);
return pq-= otherQuantity;
PQ minus;
minus += (*this);
minus -= otherQuantity;
return minus;
}
/**
* Multiply operator
*/
CPhysicalQuantity &CPhysicalQuantity::operator *=(double multiply)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ> &CPhysicalQuantity<MU,PQ>::operator *=(double multiply)
{
this->setUnitValue(this->_unitValueD *multiply);
this->setUnitValue(this->m_unitValueD *multiply);
return *this;
}
/**
* Multiply operator
*/
CPhysicalQuantity CPhysicalQuantity::operator *(double multiply) const
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator *(double multiply) const
{
CPhysicalQuantity pq= (*this);
return pq *= multiply;
PQ times;
times += (*this);
times *= multiply;
return times;
}
/**
* Divide operator /=
*/
CPhysicalQuantity &CPhysicalQuantity::operator /=(double divide)
template <class MU, class PQ> CPhysicalQuantity<MU,PQ> &CPhysicalQuantity<MU,PQ>::operator /=(double divide)
{
this->setUnitValue(this->_unitValueD / divide);
this->setUnitValue(this->m_unitValueD / divide);
return *this;
}
/**
* Divide operator /=
* Divide operator /
*/
CPhysicalQuantity CPhysicalQuantity::operator /(double divide) const
template <class MU, class PQ> PQ CPhysicalQuantity<MU,PQ>::operator /(double divide) const
{
CPhysicalQuantity pq= (*this);
return pq /= divide;
PQ div;
div += (*this);
div /= divide;
return div;
}
/**
* Less operator <
*/
bool CPhysicalQuantity::operator <(const CPhysicalQuantity &otherQuantity) const {
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator <(const CPhysicalQuantity<MU,PQ> &otherQuantity) const {
if(this == &otherQuantity) return false;
double diff = this->_convertedSiUnitValueD - otherQuantity._convertedSiUnitValueD;
return (diff < 0 && abs(diff) >= this->_pUnit.getEpsilon());
double diff = this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD;
return (diff < 0 && abs(diff) >= this->m_unit.getEpsilon());
}
bool CPhysicalQuantity::operator >(const CPhysicalQuantity &otherQuantity) const {
/**
* Greater than
*/
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator >(const CPhysicalQuantity<MU,PQ> &otherQuantity) const {
if(this == &otherQuantity) return false;
return otherQuantity < *this;
}
bool CPhysicalQuantity::operator >=(const CPhysicalQuantity &otherQuantity) const {
/**
* Greater / Equal
*/
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator >=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const {
if(this == &otherQuantity) return true;
return !(*this < otherQuantity);
}
bool CPhysicalQuantity::operator <=(const CPhysicalQuantity &otherQuantity) const {
/**
* Less equal
*/
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::operator <=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const {
if(this == &otherQuantity) return true;
return !(*this > otherQuantity);
}
@@ -253,12 +245,12 @@ bool CPhysicalQuantity::operator <=(const CPhysicalQuantity &otherQuantity) cons
/**
* Switch to another unit
*/
bool CPhysicalQuantity::switchUnit(const CMeasurementUnit &newUnit)
template <class MU, class PQ> bool CPhysicalQuantity<MU,PQ>::switchUnit(const MU &newUnit)
{
if (this->_pUnit == newUnit) return true;
if (this->_pUnit.getType() != newUnit.getType()) return false; // not possible
double cf = this->_unitConverter(this, newUnit);
this->_pUnit = newUnit;
if (this->m_unit == newUnit) return true;
if (this->m_unit.getType() != newUnit.getType()) return false; // not possible
double cf = this->m_unitConverter(this, newUnit);
this->m_unit = newUnit;
this->setUnitValue(cf);
return true;
}
@@ -266,57 +258,57 @@ bool CPhysicalQuantity::switchUnit(const CMeasurementUnit &newUnit)
/**
* Init by integer
*/
void CPhysicalQuantity::setUnitValue(qint32 baseValue)
template <class MU, class PQ> void CPhysicalQuantity<MU,PQ>::setUnitValue(qint32 baseValue)
{
this->_unitValueI= baseValue;
this->_unitValueD= double(baseValue);
this->_isIntegerBaseValue = true;
this->m_unitValueI= baseValue;
this->m_unitValueD= double(baseValue);
this->m_isIntegerBaseValue = true;
this->setConversionSiUnitValue();
}
/**
* Init by double
*/
void CPhysicalQuantity::setUnitValue(double baseValue)
template <class MU, class PQ> void CPhysicalQuantity<MU,PQ>::setUnitValue(double baseValue)
{
this->_unitValueD = baseValue;
this->_unitValueI = qRound(baseValue);
this->_isIntegerBaseValue = false;
this->m_unitValueD = baseValue;
this->m_unitValueI = qRound(baseValue);
this->m_isIntegerBaseValue = false;
this->setConversionSiUnitValue();
}
/**
* Set SI value
*/
void CPhysicalQuantity::setConversionSiUnitValue() {
this->_convertedSiUnitValueD = this->_unitConverter(this, this->_pConversionSiUnit);
template <class MU, class PQ> void CPhysicalQuantity<MU,PQ>::setConversionSiUnitValue() {
this->m_convertedSiUnitValueD = this->m_unitConverter(this, this->m_conversionSiUnit);
}
/**
* Standard conversion by factor, used in most cases, in some cases (e.g. CTemperature) arbitrary converter
*/
double CPhysicalQuantity::standardUnitFactorValueConverter(const CPhysicalQuantity *quantity, const CMeasurementUnit &otherUnit) {
if (quantity->_pUnit == CMeasurementUnit::None() || quantity->_unitValueD == 0.0) return 0.0;
if (quantity->_pUnit == otherUnit) return quantity->_unitValueD;
double f = quantity->_pUnit.conversionFactor(otherUnit);
return f * quantity->_unitValueD;
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::standardUnitFactorValueConverter(const CPhysicalQuantity<MU,PQ> *quantity, const MU &otherUnit) {
if (quantity->m_unit == MU::None() || quantity->m_unitValueD == 0.0) return 0.0;
if (quantity->m_unit == otherUnit) return quantity->m_unitValueD;
double f = quantity->m_unit.conversionFactor(otherUnit);
return f * quantity->m_unitValueD;
}
/**
* Round
*/
double CPhysicalQuantity::unitValueToDoubleRounded(int digits) const
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::unitValueToDoubleRounded(int digits) const
{
if (digits < 1) digits = this->_pUnit.getDisplayDigits();
return CPhysicalQuantity::round(this->_unitValueD, digits);
if (digits < 1) digits = this->m_unit.getDisplayDigits();
return CPhysicalQuantity<MU,PQ>::round(this->m_unitValueD, digits);
}
/**
* Rounded to QString
*/
QString CPhysicalQuantity::toQStringRounded(double value, int digits)
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::toQStringRounded(double value, int digits)
{
double v =CPhysicalQuantity::round(value, digits);
double v =CPhysicalQuantity<MU,PQ>::round(value, digits);
QString s = QLocale::system().toString(v, 'f', digits);
return s;
}
@@ -324,80 +316,80 @@ QString CPhysicalQuantity::toQStringRounded(double value, int digits)
/**
* Rounded value to QString
*/
QString CPhysicalQuantity::unitValueToQStringRounded(int digits) const
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::unitValueToQStringRounded(int digits) const
{
if (digits < 1) digits = this->_pUnit.getDisplayDigits();
return CPhysicalQuantity::toQStringRounded(this->_unitValueD, digits);
if (digits < 1) digits = this->m_unit.getDisplayDigits();
return CPhysicalQuantity<MU,PQ>::toQStringRounded(this->m_unitValueD, digits);
}
/**
* Rounded SI value to QString
*/
QString CPhysicalQuantity::convertedSiValueToQStringRounded(int digits) const
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::convertedSiValueToQStringRounded(int digits) const
{
if (digits < 1) digits = this->_pConversionSiUnit.getDisplayDigits();
return CPhysicalQuantity::toQStringRounded(this->_convertedSiUnitValueD, digits);
if (digits < 1) digits = this->m_conversionSiUnit.getDisplayDigits();
return CPhysicalQuantity<MU,PQ>::toQStringRounded(this->m_convertedSiUnitValueD, digits);
}
/**
* Value rounded in original unit
*/
QString CPhysicalQuantity::unitValueRoundedWithUnit(int digits) const {
if (digits < 1) digits = this->_pUnit.getDisplayDigits();
return this->unitValueToQStringRounded(digits).append(this->_pUnit.getUnitName());
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::unitValueRoundedWithUnit(int digits) const {
if (digits < 1) digits = this->m_unit.getDisplayDigits();
return this->unitValueToQStringRounded(digits).append(this->m_unit.getUnitName());
}
/**
* SI base unit value with unit
*/
QString CPhysicalQuantity::convertedSiValueRoundedWithUnit(int digits) const {
if (digits < 1) digits = this->_pConversionSiUnit.getDisplayDigits();
return this->convertedSiValueToQStringRounded(digits).append(this->_pConversionSiUnit.getUnitName());
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::convertedSiValueRoundedWithUnit(int digits) const {
if (digits < 1) digits = this->m_conversionSiUnit.getDisplayDigits();
return this->convertedSiValueToQStringRounded(digits).append(this->m_conversionSiUnit.getUnitName());
}
/**
* Value rounded in unit
*/
QString CPhysicalQuantity::valueRoundedWithUnit(const CMeasurementUnit &unit, int digits) const
template <class MU, class PQ> QString CPhysicalQuantity<MU,PQ>::valueRoundedWithUnit(const MU &unit, int digits) const
{
if (unit == this->_pUnit) return this->unitValueRoundedWithUnit(digits);
if (unit == this->_pConversionSiUnit) return this->convertedSiValueRoundedWithUnit(digits);
if (unit == this->m_unit) return this->unitValueRoundedWithUnit(digits);
if (unit == this->m_conversionSiUnit) return this->convertedSiValueRoundedWithUnit(digits);
if (digits < 0) digits = unit.getDisplayDigits();
return CPhysicalQuantity::toQStringRounded(this->value(unit), digits).append(unit.getUnitName());
return CPhysicalQuantity<MU,PQ>::toQStringRounded(this->value(unit), digits).append(unit.getUnitName());
}
/**
* Value rounded in unit
*/
double CPhysicalQuantity::valueRounded(const CMeasurementUnit &unit, int digits) const
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::valueRounded(const MU &unit, int digits) const
{
if (digits < 1) digits = unit.getDisplayDigits();
return CPhysicalQuantity::round(this->value(unit),digits);
return CPhysicalQuantity<MU,PQ>::round(this->value(unit),digits);
}
/**
* Value in unit
*/
double CPhysicalQuantity::value(const CMeasurementUnit &unit) const
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::value(const MU &unit) const
{
if (unit == this->_pConversionSiUnit) return this->_convertedSiUnitValueD;
double v = this->_unitConverter(this, unit);
if (unit == this->m_conversionSiUnit) return this->m_convertedSiUnitValueD;
double v = this->m_unitConverter(this, unit);
return v;
}
/**
* Round utility method
*/
double CPhysicalQuantity::convertedSiValueToDoubleRounded(int digits) const
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::convertedSiValueToDoubleRounded(int digits) const
{
if (digits < 1) digits = this->_pConversionSiUnit.getDisplayDigits();
return CPhysicalQuantity::round(this->_convertedSiUnitValueD, digits);
if (digits < 1) digits = this->m_conversionSiUnit.getDisplayDigits();
return CPhysicalQuantity<MU,PQ>::round(this->m_convertedSiUnitValueD, digits);
}
/**
* Round utility method
*/
double CPhysicalQuantity::round(double value, int digits) {
template <class MU, class PQ> double CPhysicalQuantity<MU,PQ>::round(double value, int digits) {
// gosh, is there no Qt method for this???
// It's year 2013
double m = pow(10.0,digits);
@@ -405,4 +397,14 @@ double CPhysicalQuantity::round(double value, int digits) {
return rv;
}
} // namespace BlackCore
// see here for the reason of this forward initialization
// http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html
template class CPhysicalQuantity<CDistanceUnit, CDistance>;
template class CPhysicalQuantity<CPressureUnit, CPressure>;
template class CPhysicalQuantity<CFrequencyUnit, CFrequency>;
template class CPhysicalQuantity<CMassUnit, CMass>;
template class CPhysicalQuantity<CTemperatureUnit, CTemperature>;
template class CPhysicalQuantity<CSpeedUnit, CSpeed>;
template class CPhysicalQuantity<CAngleUnit, CAngle>;
} // namespace

View File

@@ -1,65 +1,77 @@
#ifndef PQPHYSICALQUANTITY_H
#define PQPHYSICALQUANTITY_H
#include <QtGlobal>
#include <QString>
#include <QLocale>
#include "blackmisc/pqbase.h"
#include "blackmisc/pqunits.h"
#include "blackmisc/debug.h"
namespace BlackMisc {
class CPhysicalQuantity;
/*!
* Our converter function, should be implemented as static method of the quantity
* classes for clarity
*/
typedef double (*CPhysicalQuantityUnitConverter)(const CPhysicalQuantity *quantity, const CMeasurementUnit &unit);
class CAngle;
/*!
* \brief A physical quantity such as "5m", "20s", "1500ft/s"
* \author KWB
*/
class CPhysicalQuantity
template <class MU, class PQ> class CPhysicalQuantity
{
/*!
* Our converter function, should be implemented as static method of the quantity
* classes for clarity
*/
typedef double (*CPhysicalQuantityUnitConverter)(const CPhysicalQuantity<MU,PQ> *quantity, const MU &unit);
/*!
* Stream operator for debugging
* \brief operator <<
* \param debug
* \param quantity
* \return
* \remarks has to be in the header files toavoid templatelink errors
*/
friend QDebug operator<<(QDebug debug, const CPhysicalQuantity &quantity);
friend QDebug operator<<(QDebug debug, const CPhysicalQuantity<MU,PQ> &quantity) {
QString v = quantity.unitValueRoundedWithUnit(-1);
debug << v;
return debug;
}
/*!
* Stream operator for log messages
* \brief operator <<
* \param log
* \param quantity
* \return
* \remarks has to be in the header files toavoid templatelink errors
*/
friend CLogMessage operator<<(CLogMessage log, const CPhysicalQuantity &quantity);
friend CLogMessage operator<<(CLogMessage log, const CPhysicalQuantity<MU,PQ> &quantity) {
QString v = quantity.unitValueRoundedWithUnit(-1);
log << v;
return log;
}
private:
qint32 _unitValueI; //!< value backed by integer, allows sole integer arithmetic
double _unitValueD; //!< value backed by double
double _convertedSiUnitValueD; //!< SI unit value
bool _isIntegerBaseValue; //!< flag integer? / double?
CPhysicalQuantityUnitConverter _unitConverter; //! <! converts values between units
qint32 m_unitValueI; //!< value backed by integer, allows sole integer arithmetic
double m_unitValueD; //!< value backed by double
double m_convertedSiUnitValueD; //!< SI unit value
bool m_isIntegerBaseValue; //!< flag integer? / double?
CPhysicalQuantityUnitConverter m_unitConverter; //! <! converts values between units
/*!
* 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)
* (e.g. CTemperature) overridden, because arbitrary conversion is required
* \param quantity quanity
* \param otherUnit
* \return
*/
static double standardUnitFactorValueConverter(const CPhysicalQuantity *quantity, const CMeasurementUnit &otherUnit);
static double standardUnitFactorValueConverter(const CPhysicalQuantity<MU,PQ> *quantity, const MU &otherUnit);
protected:
CMeasurementUnit _pUnit; //!< unit
CMeasurementUnit _pConversionSiUnit; //!< corresponding SI base unit
MU m_unit; //!< unit
MU m_conversionSiUnit; //!< corresponding SI base unit
/*!
* \brief Constructor with int
@@ -68,7 +80,7 @@ protected:
* \param siBaseUnit
* \param unitConverter
*/
CPhysicalQuantity(qint32 baseValue, const CMeasurementUnit &unit, const CMeasurementUnit &siConversionUnit,
CPhysicalQuantity(qint32 baseValue, const MU &unit, const MU &siConversionUnit,
const CPhysicalQuantityUnitConverter unitConverter = CPhysicalQuantity::standardUnitFactorValueConverter);
/*!
* \brief Constructor with double
@@ -76,7 +88,7 @@ protected:
* \param unit
* \param siBaseUnit
*/
CPhysicalQuantity(double baseValue, const CMeasurementUnit &unit, const CMeasurementUnit &siConversionUnit,
CPhysicalQuantity(double baseValue, const MU &unit, const MU &siConversionUnit,
const CPhysicalQuantityUnitConverter unitConverter = CPhysicalQuantity::standardUnitFactorValueConverter);
/*!
* \brief Init by integer
@@ -93,39 +105,47 @@ protected:
* \brief Set the SI value
*/
void setConversionSiUnitValue();
public:
/*!
* \brief Copy constructor
* \param otherQuantity
*/
CPhysicalQuantity(const CPhysicalQuantity &otherQuantity);
CPhysicalQuantity<MU,PQ>(const CPhysicalQuantity<MU,PQ> &otherQuantity);
/*!
* \brief Virtual destructor
*/
virtual ~CPhysicalQuantity();
virtual ~CPhysicalQuantity<MU,PQ>();
/*!
* \brief Unit of the distance
* \return
*/
MU getUnit() const { return this->m_unit; }
/*!
* \brief Conversion SI unit
* \return
*/
MU getConversionSiUnit() const { return this->m_conversionSiUnit; }
/*!
* \brief Switch unit, e.g. feet meter
* \param newUnit
* \return
*/
bool switchUnit(const CMeasurementUnit &newUnit);
bool switchUnit(const MU &newUnit);
/*!
* \brief Value in SI base unit? Meter is an SI base unit, hertz not!
* \return
*/
bool isSiBaseUnit() const { return this->_pUnit.isSiBaseUnit(); }
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->_pUnit.isSiUnit(); }
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->_pUnit.isUnprefixedSiUnit(); }
bool isUnprefixedSiUnit() const { return this->m_unit.isUnprefixedSiUnit(); }
/*!
* \brief Value to QString with unit, e.g. "5.00m"
* \param digits
@@ -137,41 +157,41 @@ public:
* \param unit
* @return
*/
double value(const CMeasurementUnit &unit) const;
double value(const MU &unit) const;
/*!
* \brief Rounded value in unit
* \param unit
* \param digits
* @return
*/
double valueRounded(const CMeasurementUnit &unit, int digits = -1) const;
double valueRounded(const MU &unit, int digits = -1) const;
/*!
* \brief Value to QString with unit, e.g. "5.00m"
* \param unit
* \param digits
* @return
*/
QString valueRoundedWithUnit(const CMeasurementUnit &unit, int digits = -1) const;
QString valueRoundedWithUnit(const MU &unit, int digits = -1) const;
/*!
* \brief Value a int
* @return
*/
qint32 unitValueToInteger() const { return this->_unitValueI;}
qint32 unitValueToInteger() const { return this->m_unitValueI;}
/*!
* \brief Value a double
* @return
*/
double unitValueToDouble() const { return this->_unitValueD;}
double unitValueToDouble() const { return this->m_unitValueD;}
/*!
* \brief SI value to integer
* @return
*/
qint32 siBaseUnitValueToInteger() const { return CPhysicalQuantity::round(this->_convertedSiUnitValueD,0);}
qint32 siBaseUnitValueToInteger() const { return CPhysicalQuantity::round(this->m_convertedSiUnitValueD,0);}
/*!
* \brief SI value to double
* @return
*/
double siBaseUnitValueToDouble() const { return this->_convertedSiUnitValueD;}
double siBaseUnitValueToDouble() const { return this->m_convertedSiUnitValueD;}
/*!
* \brief Rounded value by n digits
* \param digits
@@ -188,12 +208,12 @@ public:
* \brief SI value as double
* \return
*/
double convertedSiValueToDouble() const { return this->_convertedSiUnitValueD;}
double convertedSiValueToDouble() const { return this->m_convertedSiUnitValueD;}
/*!
* \brief SI value as integer
* \return
*/
qint32 convertedSiValueToInteger() const { return (qint32)CPhysicalQuantity::round(this->_convertedSiUnitValueD,0);}
qint32 convertedSiValueToInteger() const { return (qint32)CPhysicalQuantity::round(this->m_convertedSiUnitValueD,0);}
/*!
* \brief Rounded SI value by n digits
* \param digits
@@ -212,116 +232,118 @@ public:
* @return
*/
QString convertedSiValueRoundedWithUnit(int digits = -1) const;
/*!
* \brief Add to the unit value.
* \remarks Since overloading the + operator with double did lead to unintended conversions, as explicit method
* \param value
*/
void addUnitValue(double value);
/*!
* \brief Substratc to the unit value.
* \remarks Since overloading the - operator with double did lead to unintended conversions, as explicit method
* \param value
*/
void substractUnitValue(double value);
/*!
* \brief Cast as double
*/
operator double() const { return this->_convertedSiUnitValueD; }
operator double() const { return this->m_convertedSiUnitValueD; }
/*!
* \brief Cast as QString
*/
operator QString() const { return this->unitValueRoundedWithUnit();}
/*!
* \brief Assignment operator =
* \param otherQuantity
* @return
*/
CPhysicalQuantity &operator =(const CPhysicalQuantity &otherQuantity);
/*!
* \brief Plus operator +=
* \param otherQuantity
* @return
*/
CPhysicalQuantity &operator +=(const CPhysicalQuantity &otherQuantity);
/*!
* \brief Plus operator +=
* \param unprefixedSiUnitValue
* @return
*/
CPhysicalQuantity &operator +=(double unprefixedSiUnitValue);
/*!
* \brief Minus operator-=
* \param otherQuantity
* @return
*/
CPhysicalQuantity &operator -=(const CPhysicalQuantity &otherQuantity);
/*!
* \brief Plus operator +=
* \param unprefixedSiUnitValue
* @return
*/
CPhysicalQuantity &operator -=(double unprefixedSiUnitValue);
/*!
* \brief Plus operator +
* \param otherQuantity
* @return
*/
CPhysicalQuantity operator +(const CPhysicalQuantity &otherQuantity) const;
/*!
* \brief Minus operator -
* \param otherQuantity
* @return
*/
CPhysicalQuantity operator -(const CPhysicalQuantity &otherQuantity) const;
/*!
* \brief Multiply operator *=
* \param multiply
* @return
* \return
*/
CPhysicalQuantity &operator *=(double multiply);
CPhysicalQuantity<MU,PQ> &operator *=(double multiply);
/*!
* \brief Divide operator /=
* \param divide
* @return
*/
CPhysicalQuantity &operator /=(double divide);
CPhysicalQuantity<MU,PQ> &operator /=(double divide);
/*!
* \brief Operator *
* \param multiply
* @return
*/
CPhysicalQuantity operator *(double multiply) const;
PQ operator *(double multiply) const;
/*!
* \brief Operator /
* \param divide
* @return
*/
CPhysicalQuantity operator /(double divide) const;
PQ operator /(double divide) const;
/*!
* \brief Equal operator ==
* \param otherQuantity
* @return
*/
bool operator==(const CPhysicalQuantity &otherQuantity) const;
bool operator==(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Not equal operator !=
* \param otherQuantity
* @return
*/
bool operator!=(const CPhysicalQuantity &otherQuantity) const;
bool operator!=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Plus operator +=
* \param otherQuantity
* @return
*/
CPhysicalQuantity<MU,PQ> &operator +=(const CPhysicalQuantity<MU,PQ> &otherQuantity);
/*!
* \brief Minus operator-=
* \param otherQuantity
* @return
*/
CPhysicalQuantity<MU,PQ> &operator -=(const CPhysicalQuantity<MU,PQ> &otherQuantity);
/*!
* \brief Greater operator >
* \param otherQuantity
* @return
*/
bool operator >(const CPhysicalQuantity &otherQuantity) const;
bool operator >(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Less operator <
* \param otherQuantity
* @return
*/
bool operator <(const CPhysicalQuantity &otherQuantity) const;
bool operator <(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Less equal operator <=
* \param otherQuantity
* @return
*/
bool operator <=(const CPhysicalQuantity &otherQuantity) const;
bool operator <=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Greater equal operator >=
* \param otherQuantity
* @return
*/
bool operator >=(const CPhysicalQuantity &otherQuantity) const;
bool operator >=(const CPhysicalQuantity<MU,PQ> &otherQuantity) const;
/*!
* \brief Assignment operator =
* \param otherQuantity
* @return
*/
CPhysicalQuantity<MU,PQ> &operator =(const CPhysicalQuantity<MU,PQ> &otherQuantity);
/*!
* \brief Plus operator +
* \param otherQuantity
* @return
*/
PQ operator +(const PQ &otherQuantity) const;
/*!
* \brief Minus operator -
* \param otherQuantity
* @return
*/
PQ operator -(const PQ &otherQuantity) const;
// --------------------------------------------------------------------
// -- static
@@ -343,5 +365,7 @@ public:
*/
static QString toQStringRounded(double value, int digits);
};
} // namespace BlackCore
#endif // PQPHYSICALQUANTITY_H

View File

@@ -1,46 +0,0 @@
#include "blackmisc/pqpressure.h"
namespace BlackMisc {
/**
* Default constructor
*/
CPressure::CPressure() : CPhysicalQuantity(0, CPressureUnit::Pa(), CPressureUnit::Pa())
{
// void
}
/**
* Constructor
*/
CPressure::CPressure(const CPhysicalQuantity &pressure): CPhysicalQuantity(pressure)
{
//void
}
/**
* Constructor
*/
CPressure::CPressure(qint32 value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit, CPressureUnit::Pa())
{
// void
}
/**
* Constructor
*/
CPressure::CPressure(double value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit, CPressureUnit::Pa())
{
// void
}
/**
* Destructor
*/
CPressure::~CPressure()
{
// void
}
} // namespace

View File

@@ -5,111 +5,37 @@
namespace BlackMisc {
/*!
* Specialized class for pressure (psi, hPa, bar).
* \author KWB
*/
class CPressureUnit : public CMeasurementUnit {
friend class CPressure;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* and cast unit
* \param otherUnit
*/
CPressureUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief Pressure unit
* \param name
* \param unitName
* \param isSIUnit
* \param conversionFactorToSI
* \param mulitplier
* \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, "frequency", isSIUnit, false, conversionFactorToSI, mulitplier, displayDigits, epsilon) {}
/*!
* \brief Pascal
* \return
*/
static const CPressureUnit& Pa() { static CPressureUnit Pa("pascal", "Pa", true); return Pa;}
/*!
* \brief Hectopascal
* \return
*/
static const CPressureUnit& hPa() { static CPressureUnit hPa("hectopascal", "hPa", true, CMeasurementPrefix::h().getFactor(), CMeasurementPrefix::h()); return hPa;}
/*!
* \brief Pounds per square inch
* \return
*/
static const CPressureUnit& psi() { static CPressureUnit psi("pounds per square inch", "psi", false, 6894.8, CMeasurementPrefix::One(), 2); return psi;}
/*!
* \brief Bar
* \return
*/
static const CPressureUnit& bar() { static CPressureUnit bar("bar", "bar", false, 1E5);return bar;}
/*!
* \brief Millibar, actually the same as hPa
* \return
*/
static const CPressureUnit& mbar() { static CPressureUnit bar("bar", "bar", false, 1E2);return bar;}
/*!
* \brief Inch of mercury at 0°C
* \return
*/
static const CPressureUnit& inHg() { static CPressureUnit inhg("Inch of mercury 0°C", "inHg", false, 3386.389);return inhg;}
/*!
* \brief Inch of mercury for flight level 29,92inHg = 1013,25mbar = 1013,25hPa
* \return
*/
static const CPressureUnit& inHgFL() { static CPressureUnit inhg("Inch of mercury ", "inHg", false, 3386.5307486631);return inhg;}
};
/*!
* \brief Physical unit distance
* \author KWB
*/
class CPressure : public CPhysicalQuantity
class CPressure : public CPhysicalQuantity<CPressureUnit,CPressure>
{
public:
/*!
* \brief Default constructor
*/
CPressure();
CPressure() : CPhysicalQuantity(0, CPressureUnit::Pa(), CPressureUnit::Pa()){}
/**
*\brief downcast copy constructor
*\brief Copy constructor
*/
CPressure(const CPhysicalQuantity &frequency);
CPressure(const CPressure &pressure) : CPhysicalQuantity(pressure) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CPressure(qint32 value, const CPressureUnit &unit = CPressureUnit::Pa());
CPressure(qint32 value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit, CPressureUnit::Pa()){}
/*!
*\brief Init by double value
* \param value
* \param unit
*/
CPressure(double value, const CPressureUnit &unit = CPressureUnit::Pa());
CPressure(double value, const CPressureUnit &unit) : CPhysicalQuantity(value, unit, CPressureUnit::Pa()){}
/*!
* \brief Virtual destructor
*/
virtual ~CPressure();
/*!
* \brief Unit of the distance
* \return
*/
CPressureUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CPressureUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CPressure() {}
};
} // namespace blackCore
} // namespace
#endif // PQPRESSURE_H

View File

@@ -1,45 +0,0 @@
#include "blackmisc/pqspeed.h"
namespace BlackMisc {
/**
* Default constructor
*/
CSpeed::CSpeed() : CPhysicalQuantity(0, CSpeedUnit::m_s(), CSpeedUnit::m_s())
{
// void
}
///**
// * Constructor
// */
//CSpeed::CSpeed(const CPhysicalQuantity &speed): CPhysicalQuantity(speed)
//{
// //void
//}
/**
* Constructor
*/
CSpeed::CSpeed(qint32 value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit, CSpeedUnit::m_s())
{
// void
}
/**
* Constructor
*/
CSpeed::CSpeed(double value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit, CSpeedUnit::m_s())
{
// void
}
/*!
* \brief Destructor
*/
CSpeed::~CSpeed()
{
// void
}
} // namespace

View File

@@ -4,101 +4,37 @@
namespace BlackMisc {
/*!
* Specialized class for speed units (m/s, ft/s, NM/h).
* \author KWB
*/
class CSpeedUnit : public CMeasurementUnit {
public:
/*!
* Constructor
* \brief CSpeedUnit
* \param name
* \param unitName
* \param isSIUnit
* \param isSIBaseUnit
* \param conversionFactorToSI
* \param mulitplier
* \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) {}
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CSpeedUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
/*!
* \brief Meter/second m/s
* \return
*/
static const CSpeedUnit& m_s() { static CSpeedUnit ms("meter/second", "m/s", true, false); return ms;}
/*!
* \brief Nautical miles per hour NM/h
* \return
*/
static const CSpeedUnit& NM_h() { static CSpeedUnit NMh("nautical miles/hour", "NM/h", false, false, 1852.0/3600.0, CMeasurementPrefix::One(), 1);return NMh;}
/*!
* \brief Feet/second ft/s
* \return
*/
static const CSpeedUnit& ft_s() { static CSpeedUnit fts("feet/seconds", "ft/s", false, false, 0.3048, CMeasurementPrefix::One(), 0); return fts;}
/*!
* \brief Feet/min ft/min
* \return
*/
static const CSpeedUnit& ft_min() { static CSpeedUnit ftmin("feet/minute", "ft/min", false, false, 0.3048 / 60.0, CMeasurementPrefix::One(), 0); return ftmin;}
/*!
* \brief Kilometer/hour km/h
* \return
*/
static const CSpeedUnit& km_h() { static CSpeedUnit kmh("kilometer/hour", "km/h", false, false, 1.0/3.6, CMeasurementPrefix::One(), 1);return kmh;}
};
/*!
* Speed class, e.g. "m/s", "NM/h", "km/h", "ft/s"
* \author KWB
*/
class CSpeed : public CPhysicalQuantity
class CSpeed : public CPhysicalQuantity<CSpeedUnit, CSpeed>
{
friend class CSpeedUnit;
private:
/**
*\brief Downcast copy constructor, allows casting units
*/
CSpeed(const CPhysicalQuantity &speed);
public:
/*!
* \brief Default constructor
*/
CSpeed();
CSpeed() : CPhysicalQuantity(0, CSpeedUnit::m_s(), CSpeedUnit::m_s()) {}
/**
*\brief Copy constructor
*/
CSpeed(const CPhysicalQuantity &speed): CPhysicalQuantity(speed) {}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CSpeed(qint32 value, const CSpeedUnit &unit = CSpeedUnit::m_s());
CSpeed(qint32 value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit, CSpeedUnit::m_s()) {}
/*!
*\brief Init by double value
* \param value
* \param unit
*/
CSpeed(double value, const CSpeedUnit &unit = CSpeedUnit::m_s());
CSpeed(double value, const CSpeedUnit &unit) : CPhysicalQuantity(value, unit, CSpeedUnit::m_s()) {}
/*!
* \brief Destructor
*/
virtual ~CSpeed();
/*!
* \brief Unit of the distance
* \return
*/
CSpeedUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CSpeedUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CSpeed() {}
};
} // namespace

View File

@@ -2,61 +2,21 @@
namespace BlackMisc {
/**
* Default Constructor
*/
CTemperature::CTemperature(): CPhysicalQuantity(0, CTemperatureUnit::K(),CTemperatureUnit::K(), CTemperature::temperaturUnitConverter)
{
// void
}
/**
* Constructor
*/
CTemperature::CTemperature(const CPhysicalQuantity &temperature): CPhysicalQuantity(temperature)
{
// void
}
/**
* Constructor
*/
CTemperature::CTemperature(qint32 value, const CTemperatureUnit &unit) : CPhysicalQuantity(value, unit, CTemperatureUnit::K(), CTemperature::temperaturUnitConverter)
{
// void
}
/**
* Constructor
*/
CTemperature::CTemperature(double value, const CTemperatureUnit &unit) : CPhysicalQuantity(value, unit, CTemperatureUnit::K(), CTemperature::temperaturUnitConverter)
{
// void
}
/**
* Destructor
*/
CTemperature::~CTemperature()
{
// void
}
/**
* Specialized method for temperture
*/
double CTemperature::temperaturUnitConverter(const CPhysicalQuantity *quantity, const CMeasurementUnit &otherUnit)
double CTemperature::temperaturUnitConverter(const CPhysicalQuantity<CTemperatureUnit, CTemperature> *quantity, const CTemperatureUnit &otherUnit)
{
CTemperature *me = (CTemperature*) quantity; // allow me access to protected
if (me->_pUnit == otherUnit) return me->siBaseUnitValueToDouble();
if (me->m_unit == otherUnit) return me->siBaseUnitValueToDouble();
double siValue;
// I always convert via SI Unit, other I would need too many conversions
if(otherUnit == me->_pConversionSiUnit) {
if(otherUnit == me->m_conversionSiUnit) {
// here I expect a conversion to SI is required and not done yet
if(me->_pUnit == CTemperatureUnit::C()) {
if(me->m_unit == CTemperatureUnit::C()) {
siValue = quantity->unitValueToDouble() + 273.15;
} else if(me->_pUnit == CTemperatureUnit::F()) {
} else if(me->m_unit == CTemperatureUnit::F()) {
siValue = (me->unitValueToDouble() + 459.67) *5.0 / 9.0;
} else{
// TODO: EXCEPTION
@@ -67,14 +27,14 @@ double CTemperature::temperaturUnitConverter(const CPhysicalQuantity *quantity,
}
// from SI
if (otherUnit == me->_pConversionSiUnit) return siValue;
if (otherUnit == me->m_conversionSiUnit) return siValue;
if(otherUnit == CTemperatureUnit::C()) {
return siValue - 273.15;
} else if(me->_pUnit == CTemperatureUnit::F()) {
} else if(me->m_unit == CTemperatureUnit::F()) {
return (siValue * 9.0 / 5.0) - 459.67;
}
// TODO: Exception
return 0;
}
} // namespace BlackCore
} // namespace

View File

@@ -4,55 +4,11 @@
namespace BlackMisc {
/*!
* Specialized class for temperatur units (kelvin, centidegree).
* \author KWB
*/
class CTemperatureUnit : public CMeasurementUnit {
friend class CTemperature;
private:
/*!
* Downcast copy constructor, allows to implement methods in base class
* \param otherUnit
*/
CTemperatureUnit(const CMeasurementUnit &otherUnit) : CMeasurementUnit(otherUnit) {}
public:
/*!
* Constructor
* \brief Temperature unit
* \param name
* \param unitName
* \param isSIUnit
* \param isSIBaseUnit
* \param conversionFactorToSI
* \param mulitplier
* \param displayDigits
* \param epsilon
*/
CTemperatureUnit(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, "temperature", isSIUnit, isSIBaseUnit, conversionFactorToSI, mulitplier, displayDigits, epsilon) {}
/*!
* \brief Kelvin
* \return
*/
static const CTemperatureUnit& K() { static CTemperatureUnit K("Kelvin", "K", true, true); return K;}
/*!
* \brief Centigrade C
* \return
*/
static const CTemperatureUnit& C() { static CTemperatureUnit C("centigrade", "°C", false, false);return C;}
/*!
* \brief Fahrenheit F
* \return
*/
static const CTemperatureUnit& F() { static CTemperatureUnit F("Fahrenheit", "°F", false, false, 5.0/9.0);return F;}
};
/*!
* \brief Physical unit temperature
* \author KWB
*/
class CTemperature : public CPhysicalQuantity
class CTemperature : public CPhysicalQuantity<CTemperatureUnit,CTemperature>
{
private:
/*!
@@ -61,42 +17,33 @@ private:
* \param otherUnit
* \return
*/
static double temperaturUnitConverter(const CPhysicalQuantity *quantity, const CMeasurementUnit &otherUnit);
static double temperaturUnitConverter(const CPhysicalQuantity<CTemperatureUnit,CTemperature> *quantity, const CTemperatureUnit &otherUnit);
public:
/*!
* \brief Default constructor
*/
CTemperature();
CTemperature() : CPhysicalQuantity(0, CTemperatureUnit::K(), CTemperatureUnit::K(), CTemperature::temperaturUnitConverter) {}
/**
*\brief downcast copy constructor
*\brief Copy constructor
*/
CTemperature(const CPhysicalQuantity &temperature);
CTemperature(const CTemperature &temperature) : CPhysicalQuantity(temperature){}
/*!
* \brief Init by int value
* \param value
* \param unit
*/
CTemperature(qint32 value, const CTemperatureUnit &unit = CTemperatureUnit::K());
CTemperature(qint32 value, const CTemperatureUnit &unit): CPhysicalQuantity(value, unit, CTemperatureUnit::K(), CTemperature::temperaturUnitConverter) {}
/*!
*\brief Init by double value
* \param value
* \param unit
*/
CTemperature(double value, const CTemperatureUnit &unit = CTemperatureUnit::K());
CTemperature(double value, const CTemperatureUnit &unit): CPhysicalQuantity(value, unit, CTemperatureUnit::K(), CTemperature::temperaturUnitConverter) {}
/*!
* \brief Destructor
*/
virtual ~CTemperature();
/*!
* \brief Unit of the temperature
* \return
*/
CTemperatureUnit getUnit() const { return this->_pUnit; }
/*!
* \brief Conversion SI unit
* \return
*/
CTemperatureUnit getConversionSiUnit() const { return this->_pConversionSiUnit; }
virtual ~CTemperature() {}
};
} // namespace

View File

@@ -37,9 +37,9 @@ void TestPhysicalQuantitiesBase::unitsBasics()
*/
void TestPhysicalQuantitiesBase::distanceBasics()
{
CDistance d1(1); // 1m
CDistance d1(1,CDistanceUnit::m()); // 1m
CDistance d2(100, CDistanceUnit::cm());
CDistance d3(1.852 * 1000); // 1852m
CDistance d3(1.852 * 1000,CDistanceUnit::m()); // 1852m
CDistance d4(1,CDistanceUnit::NM());
QVERIFY2(d1 == d2, "1meter shall be 100cm");
@@ -54,11 +54,11 @@ void TestPhysicalQuantitiesBase::distanceBasics()
QVERIFY2(!(d1 > d2), "Nothing shall be less / greater");
// epsilon tests
d1 += d1.getUnit().getEpsilon(); // this should be still the same
d1.addUnitValue(d1.getUnit().getEpsilon()); // this should be still the same
QVERIFY2(d1 == d2, "Epsilon: 1meter+epsilon shall be 100cm");
QVERIFY2(!(d1 != d2), "Epsilon: 1meter+epsilon shall be 100cm");
d1 += d1.getUnit().getEpsilon(); // now over epsilon threshold
d1.addUnitValue(d1.getUnit().getEpsilon()); // now over epsilon threshold
QVERIFY2(d1 != d2, "Epsilon exceeded: 1meter+2epsilon shall not be 100cm");
QVERIFY2(d1 > d2, "d1 shall be greater");
}
@@ -82,7 +82,7 @@ void TestPhysicalQuantitiesBase::frequencyTests()
CFrequency f1(1, CFrequencyUnit::MHz());
QVERIFY2(f1.valueRounded(CFrequencyUnit::kHz(),2) == 1000, "Mega is 1000kHz");
QVERIFY2(f1 == 1000000 , "MHz is 1E6 Hz");
CFrequency f2 = CMeasurementPrefix::M(); // 1 Megahertz
CFrequency f2(CMeasurementPrefix::M(),CFrequencyUnit::Hz()) ; // 1 Megahertz
QVERIFY2(f1 == f2 , "MHz is 1E6 Hz");
}
@@ -92,7 +92,7 @@ void TestPhysicalQuantitiesBase::frequencyTests()
void TestPhysicalQuantitiesBase::angleTests()
{
CAngle a1(180, CAngleUnit::deg());
CAngle a2(1.5 * CAngle::pi());
CAngle a2(1.5 * CAngle::pi(), CAngleUnit::rad());
a2.switchUnit(CAngleUnit::deg());
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())));
@@ -103,8 +103,8 @@ void TestPhysicalQuantitiesBase::angleTests()
*/
void TestPhysicalQuantitiesBase::massTests()
{
CMass w1(1000);
CMass w2(w1);
CMass w1(1000, CMassUnit::kg());
CMass w2(w1, CMassUnit::kg());
w2.switchUnit(CMassUnit::t());
QVERIFY2(w2.unitValueToInteger() == 1, "1tonne shall be 1000kg");
w2.switchUnit(CMassUnit::lb());
@@ -140,25 +140,41 @@ void TestPhysicalQuantitiesBase::temperatureTests()
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
* @brief Just testing obvious memory create / destruct flaws
*/
void TestPhysicalQuantitiesBase::memoryTests()
{
CDistance* c = new CDistance(100);
CDistance* c = new CDistance(100, CDistanceUnit::m());
c->switchUnit(CDistanceUnit::NM());
QVERIFY2(c->getUnit() == CDistanceUnit::NM() && c->getConversionSiUnit() == CDistanceUnit::m(),
"Testing distance units failed");
delete c;
CAngle* a = new CAngle(100);
CAngle* a = new CAngle(100, CAngleUnit::rad());
a->switchUnit(CAngleUnit::deg());
QVERIFY2(a->getUnit() == CAngleUnit::deg() && c->getConversionSiUnit() == CAngleUnit::rad(),
"Testing angle units failed");
delete a;
}
/**
* @brief Just testing obvious memory create / destruct flaws
*/
void TestPhysicalQuantitiesBase::basicArithmetic()
{
CPressure p1 = CPhysicalQuantitiesConstants::InternationalStandardSeaLevelPressure();
CPressure p2(p1);
p2 *= 2.0;
CPressure p3 = p1 + p1;
QVERIFY2(p3 == p2, "Pressure needs to be the same (2times)");
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");
}
} // namespace

View File

@@ -53,9 +53,14 @@ private slots:
*/
void temperatureTests();
/*!
* \brief testing construction / destruction in memory
* \brief Testing construction / destruction in memory
*/
void memoryTests();
/*!
* \brief Basic arithmetic such as +/-
*/
void basicArithmetic();
};
}