@@ -488,7 +488,7 @@ static inline Quantity pyToQuantity(const Py::Object &pyobj,
|
||||
}
|
||||
|
||||
Py::Object pyFromQuantity(const Quantity &quantity) {
|
||||
if(!quantity.getUnit().isEmpty())
|
||||
if (!quantity.isDimensionless())
|
||||
return Py::asObject(new QuantityPy(new Quantity(quantity)));
|
||||
double v = quantity.getValue();
|
||||
long l;
|
||||
|
||||
@@ -145,7 +145,7 @@ FeatureTest::FeatureTest()
|
||||
ADD_PROPERTY(QuantityLength, (1.0));
|
||||
QuantityLength.setUnit(Base::Unit::Length);
|
||||
ADD_PROPERTY(QuantityOther, (5.0));
|
||||
QuantityOther.setUnit(Base::Unit(-3, 1));
|
||||
QuantityOther.setUnit(Base::Unit::Density);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ void PropertyVector::getPaths(std::vector<ObjectIdentifier>& paths) const
|
||||
const boost::any PropertyVector::getPathValue(const ObjectIdentifier& path) const
|
||||
{
|
||||
Base::Unit unit = getUnit();
|
||||
if (!unit.isEmpty()) {
|
||||
if (unit != Unit::One) {
|
||||
std::string p = path.getSubPathStr();
|
||||
if (p == ".x" || p == ".y" || p == ".z") {
|
||||
// Convert double to quantity
|
||||
@@ -207,7 +207,7 @@ const boost::any PropertyVector::getPathValue(const ObjectIdentifier& path) cons
|
||||
bool PropertyVector::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const
|
||||
{
|
||||
Base::Unit unit = getUnit();
|
||||
if (unit.isEmpty()) {
|
||||
if (unit == Unit::One) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,13 +105,12 @@ void PropertyQuantity::setPyObject(PyObject* value)
|
||||
else {
|
||||
Base::Quantity quant = createQuantityFromPy(value);
|
||||
|
||||
Unit unit = quant.getUnit();
|
||||
if (unit.isEmpty()) {
|
||||
if (quant.isDimensionless()) {
|
||||
PropertyFloat::setValue(quant.getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (unit != _Unit) {
|
||||
if (_Unit != quant.getUnit()) {
|
||||
throw Base::UnitsMismatchError("Not matching Unit!");
|
||||
}
|
||||
|
||||
@@ -123,7 +122,7 @@ void PropertyQuantity::setPathValue(const ObjectIdentifier& /*path*/, const boos
|
||||
{
|
||||
auto q = App::anyToQuantity(value);
|
||||
aboutToSetValue();
|
||||
if (!q.getUnit().isEmpty()) {
|
||||
if (!q.isDimensionless()) {
|
||||
_Unit = q.getUnit();
|
||||
}
|
||||
_dValue = q.getValue();
|
||||
@@ -187,7 +186,6 @@ void PropertyQuantityConstraint::setPyObject(PyObject* value)
|
||||
{
|
||||
Base::Quantity quant = createQuantityFromPy(value);
|
||||
|
||||
Unit unit = quant.getUnit();
|
||||
double temp = quant.getValue();
|
||||
if (_ConstStruct) {
|
||||
if (temp > _ConstStruct->UpperBound) {
|
||||
@@ -199,12 +197,12 @@ void PropertyQuantityConstraint::setPyObject(PyObject* value)
|
||||
}
|
||||
quant.setValue(temp);
|
||||
|
||||
if (unit.isEmpty()) {
|
||||
if (quant.isDimensionless()) {
|
||||
PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method
|
||||
return;
|
||||
}
|
||||
|
||||
if (unit != _Unit) {
|
||||
if (_Unit != quant.getUnit()) {
|
||||
throw Base::UnitsMismatchError("Not matching Unit!");
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ Quantity Quantity::operator/(double factor) const
|
||||
|
||||
Quantity Quantity::pow(const Quantity& other) const
|
||||
{
|
||||
if (!other.myUnit.isEmpty()) {
|
||||
if (!other.isDimensionless()) {
|
||||
throw Base::UnitsMismatchError("Quantity::pow(): exponent must not have a unit");
|
||||
}
|
||||
|
||||
@@ -270,10 +270,10 @@ std::string Quantity::getSafeUserString() const
|
||||
return Tools::escapeQuotesFromString(userStr);
|
||||
}
|
||||
|
||||
/// true if it has a number without a unit
|
||||
/// true if unit equals to 1, therefore quantity has no dimension
|
||||
bool Quantity::isDimensionless() const
|
||||
{
|
||||
return isValid() && myUnit.isEmpty();
|
||||
return myUnit == Unit::One;
|
||||
}
|
||||
|
||||
/// true if it has a specific unit or no dimension.
|
||||
@@ -282,12 +282,6 @@ bool Quantity::isDimensionlessOrUnit(const Unit& unit) const
|
||||
return isDimensionless() || myUnit == unit;
|
||||
}
|
||||
|
||||
// true if it has a number and a valid unit
|
||||
bool Quantity::isQuantity() const
|
||||
{
|
||||
return isValid() && !myUnit.isEmpty();
|
||||
}
|
||||
|
||||
// true if it has a number with or without a unit
|
||||
bool Quantity::isValid() const
|
||||
{
|
||||
@@ -300,162 +294,150 @@ void Quantity::setInvalid()
|
||||
}
|
||||
|
||||
// === Predefined types =====================================================
|
||||
// clang-format off
|
||||
const Quantity Quantity::NanoMetre ( 1.0e-6 , Unit::Length );
|
||||
const Quantity Quantity::MicroMetre ( 1.0e-3 , Unit::Length );
|
||||
const Quantity Quantity::MilliMetre ( 1.0 , Unit::Length );
|
||||
const Quantity Quantity::CentiMetre ( 10.0 , Unit::Length );
|
||||
const Quantity Quantity::DeciMetre ( 100.0 , Unit::Length );
|
||||
const Quantity Quantity::Metre ( 1.0e3 , Unit::Length );
|
||||
const Quantity Quantity::KiloMetre ( 1.0e6 , Unit::Length );
|
||||
|
||||
const Quantity Quantity::NanoMetre(1.0e-6, Unit(1));
|
||||
const Quantity Quantity::MicroMetre(1.0e-3, Unit(1));
|
||||
const Quantity Quantity::MilliMetre(1.0, Unit(1));
|
||||
const Quantity Quantity::CentiMetre(10.0, Unit(1));
|
||||
const Quantity Quantity::DeciMetre(100.0, Unit(1));
|
||||
const Quantity Quantity::Metre(1.0e3, Unit(1));
|
||||
const Quantity Quantity::KiloMetre(1.0e6, Unit(1));
|
||||
const Quantity Quantity::MilliLiter ( 1000.0 , Unit::Volume );
|
||||
const Quantity Quantity::Liter ( 1.0e6 , Unit::Volume );
|
||||
|
||||
const Quantity Quantity::MilliLiter(1000.0, Unit(3));
|
||||
const Quantity Quantity::Liter(1.0e6, Unit(3));
|
||||
const Quantity Quantity::Hertz ( 1.0 , Unit::Frequency );
|
||||
const Quantity Quantity::KiloHertz ( 1.0e3 , Unit::Frequency );
|
||||
const Quantity Quantity::MegaHertz ( 1.0e6 , Unit::Frequency );
|
||||
const Quantity Quantity::GigaHertz ( 1.0e9 , Unit::Frequency );
|
||||
const Quantity Quantity::TeraHertz ( 1.0e12 , Unit::Frequency );
|
||||
|
||||
const Quantity Quantity::Hertz(1.0, Unit(0, 0, -1));
|
||||
const Quantity Quantity::KiloHertz(1.0e3, Unit(0, 0, -1));
|
||||
const Quantity Quantity::MegaHertz(1.0e6, Unit(0, 0, -1));
|
||||
const Quantity Quantity::GigaHertz(1.0e9, Unit(0, 0, -1));
|
||||
const Quantity Quantity::TeraHertz(1.0e12, Unit(0, 0, -1));
|
||||
const Quantity Quantity::MicroGram ( 1.0e-9 , Unit::Mass );
|
||||
const Quantity Quantity::MilliGram ( 1.0e-6 , Unit::Mass );
|
||||
const Quantity Quantity::Gram ( 1.0e-3 , Unit::Mass );
|
||||
const Quantity Quantity::KiloGram ( 1.0 , Unit::Mass );
|
||||
const Quantity Quantity::Ton ( 1.0e3 , Unit::Mass );
|
||||
|
||||
const Quantity Quantity::MicroGram(1.0e-9, Unit(0, 1));
|
||||
const Quantity Quantity::MilliGram(1.0e-6, Unit(0, 1));
|
||||
const Quantity Quantity::Gram(1.0e-3, Unit(0, 1));
|
||||
const Quantity Quantity::KiloGram(1.0, Unit(0, 1));
|
||||
const Quantity Quantity::Ton(1.0e3, Unit(0, 1));
|
||||
const Quantity Quantity::Second ( 1.0 , Unit::TimeSpan );
|
||||
const Quantity Quantity::Minute ( 60.0 , Unit::TimeSpan );
|
||||
const Quantity Quantity::Hour ( 3600.0 , Unit::TimeSpan );
|
||||
|
||||
const Quantity Quantity::Second(1.0, Unit(0, 0, 1));
|
||||
const Quantity Quantity::Minute(60.0, Unit(0, 0, 1));
|
||||
const Quantity Quantity::Hour(3600.0, Unit(0, 0, 1));
|
||||
const Quantity Quantity::Ampere ( 1.0 , Unit::ElectricCurrent );
|
||||
const Quantity Quantity::MilliAmpere ( 0.001 , Unit::ElectricCurrent );
|
||||
const Quantity Quantity::KiloAmpere ( 1000.0 , Unit::ElectricCurrent );
|
||||
const Quantity Quantity::MegaAmpere ( 1.0e6 , Unit::ElectricCurrent );
|
||||
|
||||
const Quantity Quantity::Ampere(1.0, Unit(0, 0, 0, 1));
|
||||
const Quantity Quantity::MilliAmpere(0.001, Unit(0, 0, 0, 1));
|
||||
const Quantity Quantity::KiloAmpere(1000.0, Unit(0, 0, 0, 1));
|
||||
const Quantity Quantity::MegaAmpere(1.0e6, Unit(0, 0, 0, 1));
|
||||
const Quantity Quantity::Kelvin ( 1.0 , Unit::Temperature );
|
||||
const Quantity Quantity::MilliKelvin ( 0.001 , Unit::Temperature );
|
||||
const Quantity Quantity::MicroKelvin ( 0.000001 , Unit::Temperature );
|
||||
|
||||
const Quantity Quantity::Kelvin(1.0, Unit(0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::MilliKelvin(0.001, Unit(0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::MicroKelvin(0.000001, Unit(0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::MilliMole ( 0.001 , Unit::AmountOfSubstance );
|
||||
const Quantity Quantity::Mole ( 1.0 , Unit::AmountOfSubstance );
|
||||
|
||||
const Quantity Quantity::MilliMole(0.001, Unit(0, 0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::Mole(1.0, Unit(0, 0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::Candela ( 1.0 , Unit::LuminousIntensity );
|
||||
|
||||
const Quantity Quantity::Candela(1.0, Unit(0, 0, 0, 0, 0, 0, 1));
|
||||
const Quantity Quantity::Inch ( 25.4 , Unit::Length );
|
||||
const Quantity Quantity::Foot ( 304.8 , Unit::Length );
|
||||
const Quantity Quantity::Thou ( 0.0254 , Unit::Length );
|
||||
const Quantity Quantity::Yard ( 914.4 , Unit::Length );
|
||||
const Quantity Quantity::Mile ( 1609344.0 , Unit::Length );
|
||||
|
||||
const Quantity Quantity::Inch(25.4, Unit(1));
|
||||
const Quantity Quantity::Foot(304.8, Unit(1));
|
||||
const Quantity Quantity::Thou(0.0254, Unit(1));
|
||||
const Quantity Quantity::Yard(914.4, Unit(1));
|
||||
const Quantity Quantity::Mile(1609344.0, Unit(1));
|
||||
const Quantity Quantity::MilePerHour ( 447.04 , Unit::Velocity );
|
||||
const Quantity Quantity::SquareFoot ( 92903.04 , Unit::Area );
|
||||
const Quantity Quantity::CubicFoot ( 28316846.592 , Unit::Volume );
|
||||
|
||||
const Quantity Quantity::MilePerHour(447.04, Unit(1, 0, -1));
|
||||
const Quantity Quantity::SquareFoot(92903.04, Unit(2));
|
||||
const Quantity Quantity::CubicFoot(28316846.592, Unit(3));
|
||||
const Quantity Quantity::Pound ( 0.45359237 , Unit::Mass );
|
||||
const Quantity Quantity::Ounce ( 0.0283495231 , Unit::Mass );
|
||||
const Quantity Quantity::Stone ( 6.35029318 , Unit::Mass );
|
||||
const Quantity Quantity::Hundredweights ( 50.80234544 , Unit::Mass );
|
||||
|
||||
const Quantity Quantity::Pound(0.45359237, Unit(0, 1));
|
||||
const Quantity Quantity::Ounce(0.0283495231, Unit(0, 1));
|
||||
const Quantity Quantity::Stone(6.35029318, Unit(0, 1));
|
||||
const Quantity Quantity::Hundredweights(50.80234544, Unit(0, 1));
|
||||
const Quantity Quantity::PoundForce ( 4448.22 , Unit::Force ); // lbf are ~= 4.44822 Newton
|
||||
|
||||
const Quantity Quantity::PoundForce(4448.22, Unit(1, 1, -2)); // lbf are ~= 4.44822 Newton
|
||||
const Quantity Quantity::Newton ( 1000.0 , Unit::Force ); // Newton (kg*m/s^2)
|
||||
const Quantity Quantity::MilliNewton ( 1.0 , Unit::Force );
|
||||
const Quantity Quantity::KiloNewton ( 1e+6 , Unit::Force );
|
||||
const Quantity Quantity::MegaNewton ( 1e+9 , Unit::Force );
|
||||
|
||||
const Quantity Quantity::Newton(1000.0, Unit(1, 1, -2)); // Newton (kg*m/s^2)
|
||||
const Quantity Quantity::MilliNewton(1.0, Unit(1, 1, -2));
|
||||
const Quantity Quantity::KiloNewton(1e+6, Unit(1, 1, -2));
|
||||
const Quantity Quantity::MegaNewton(1e+9, Unit(1, 1, -2));
|
||||
const Quantity Quantity::NewtonPerMeter ( 1.00 , Unit::Stiffness ); // Newton per meter (N/m or kg/s^2)
|
||||
const Quantity Quantity::MilliNewtonPerMeter ( 1e-3 , Unit::Stiffness );
|
||||
const Quantity Quantity::KiloNewtonPerMeter ( 1e3 , Unit::Stiffness );
|
||||
const Quantity Quantity::MegaNewtonPerMeter ( 1e6 , Unit::Stiffness );
|
||||
|
||||
const Quantity Quantity::NewtonPerMeter(1.00, Unit(0, 1, -2)); // Newton per meter (N/m or kg/s^2)
|
||||
const Quantity Quantity::MilliNewtonPerMeter(1e-3, Unit(0, 1, -2));
|
||||
const Quantity Quantity::KiloNewtonPerMeter(1e3, Unit(0, 1, -2));
|
||||
const Quantity Quantity::MegaNewtonPerMeter(1e6, Unit(0, 1, -2));
|
||||
const Quantity Quantity::Pascal ( 0.001 , Unit::CompressiveStrength ); // Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity Quantity::KiloPascal ( 1.00 , Unit::CompressiveStrength );
|
||||
const Quantity Quantity::MegaPascal ( 1000.0 , Unit::CompressiveStrength );
|
||||
const Quantity Quantity::GigaPascal ( 1e+6 , Unit::CompressiveStrength );
|
||||
|
||||
const Quantity Quantity::Pascal(0.001, Unit(-1, 1, -2)); // Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity Quantity::KiloPascal(1.00, Unit(-1, 1, -2));
|
||||
const Quantity Quantity::MegaPascal(1000.0, Unit(-1, 1, -2));
|
||||
const Quantity Quantity::GigaPascal(1e+6, Unit(-1, 1, -2));
|
||||
const Quantity Quantity::MilliBar ( 0.1 , Unit::CompressiveStrength );
|
||||
const Quantity Quantity::Bar ( 100.0 , Unit::CompressiveStrength ); // 1 bar = 100 kPa
|
||||
|
||||
const Quantity Quantity::MilliBar(0.1, Unit(-1, 1, -2));
|
||||
const Quantity Quantity::Bar(100.0, Unit(-1, 1, -2)); // 1 bar = 100 kPa
|
||||
const Quantity Quantity::Torr ( 101.325 / 760.0 , Unit::CompressiveStrength ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity Quantity::mTorr ( 0.101325 / 760.0 , Unit::CompressiveStrength ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity Quantity::yTorr ( 0.000101325 / 760.0 , Unit::CompressiveStrength ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
|
||||
const Quantity
|
||||
Quantity::Torr(101.325 / 760.0,
|
||||
Unit(-1, 1, -2)); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity
|
||||
Quantity::mTorr(0.101325 / 760.0,
|
||||
Unit(-1, 1, -2)); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity
|
||||
Quantity::yTorr(0.000101325 / 760.0,
|
||||
Unit(-1, 1, -2)); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
|
||||
const Quantity Quantity::PSI ( 6.894744825494 , Unit::CompressiveStrength ); // pounds/in^2
|
||||
const Quantity Quantity::KSI ( 6894.744825494 , Unit::CompressiveStrength ); // 1000 x pounds/in^2
|
||||
const Quantity Quantity::MPSI ( 6894744.825494 , Unit::CompressiveStrength ); // 1000 ksi
|
||||
|
||||
const Quantity Quantity::PSI(6.894744825494, Unit(-1, 1, -2)); // pounds/in^2
|
||||
const Quantity Quantity::KSI(6894.744825494, Unit(-1, 1, -2)); // 1000 x pounds/in^2
|
||||
const Quantity Quantity::MPSI(6894744.825494, Unit(-1, 1, -2)); // 1000 ksi
|
||||
const Quantity Quantity::Watt ( 1e+6 , Unit::Power ); // Watt (kg*m^2/s^3)
|
||||
const Quantity Quantity::MilliWatt ( 1e+3 , Unit::Power );
|
||||
const Quantity Quantity::KiloWatt ( 1e+9 , Unit::Power );
|
||||
const Quantity Quantity::VoltAmpere ( 1e+6 , Unit::Power ); // VoltAmpere (kg*m^2/s^3)
|
||||
|
||||
const Quantity Quantity::Watt(1e+6, Unit(2, 1, -3)); // Watt (kg*m^2/s^3)
|
||||
const Quantity Quantity::MilliWatt(1e+3, Unit(2, 1, -3));
|
||||
const Quantity Quantity::KiloWatt(1e+9, Unit(2, 1, -3));
|
||||
const Quantity Quantity::VoltAmpere(1e+6, Unit(2, 1, -3)); // VoltAmpere (kg*m^2/s^3)
|
||||
const Quantity Quantity::Volt ( 1e+6 , Unit::ElectricPotential ); // Volt (kg*m^2/A/s^3)
|
||||
const Quantity Quantity::MilliVolt ( 1e+3 , Unit::ElectricPotential );
|
||||
const Quantity Quantity::KiloVolt ( 1e+9 , Unit::ElectricPotential );
|
||||
|
||||
const Quantity Quantity::Volt(1e+6, Unit(2, 1, -3, -1)); // Volt (kg*m^2/A/s^3)
|
||||
const Quantity Quantity::MilliVolt(1e+3, Unit(2, 1, -3, -1));
|
||||
const Quantity Quantity::KiloVolt(1e+9, Unit(2, 1, -3, -1));
|
||||
const Quantity Quantity::MegaSiemens ( 1.0 , Unit::ElectricalConductance );
|
||||
const Quantity Quantity::KiloSiemens ( 1e-3 , Unit::ElectricalConductance );
|
||||
const Quantity Quantity::Siemens ( 1e-6 , Unit::ElectricalConductance ); // Siemens (A^2*s^3/kg/m^2)
|
||||
const Quantity Quantity::MilliSiemens ( 1e-9 , Unit::ElectricalConductance );
|
||||
const Quantity Quantity::MicroSiemens ( 1e-12 , Unit::ElectricalConductance );
|
||||
|
||||
const Quantity Quantity::MegaSiemens(1.0, Unit(-2, -1, 3, 2));
|
||||
const Quantity Quantity::KiloSiemens(1e-3, Unit(-2, -1, 3, 2));
|
||||
const Quantity Quantity::Siemens(1e-6, Unit(-2, -1, 3, 2)); // Siemens (A^2*s^3/kg/m^2)
|
||||
const Quantity Quantity::MilliSiemens(1e-9, Unit(-2, -1, 3, 2));
|
||||
const Quantity Quantity::MicroSiemens(1e-12, Unit(-2, -1, 3, 2));
|
||||
const Quantity Quantity::Ohm ( 1e+6 , Unit::ElectricalResistance ); // Ohm (kg*m^2/A^2/s^3)
|
||||
const Quantity Quantity::KiloOhm ( 1e+9 , Unit::ElectricalResistance );
|
||||
const Quantity Quantity::MegaOhm ( 1e+12 , Unit::ElectricalResistance );
|
||||
|
||||
const Quantity Quantity::Ohm(1e+6, Unit(2, 1, -3, -2)); // Ohm (kg*m^2/A^2/s^3)
|
||||
const Quantity Quantity::KiloOhm(1e+9, Unit(2, 1, -3, -2));
|
||||
const Quantity Quantity::MegaOhm(1e+12, Unit(2, 1, -3, -2));
|
||||
const Quantity Quantity::Coulomb ( 1.0 , Unit::ElectricCharge ); // Coulomb (A*s)
|
||||
|
||||
const Quantity Quantity::Coulomb(1.0, Unit(0, 0, 1, 1)); // Coulomb (A*s)
|
||||
const Quantity Quantity::Tesla ( 1.0 , Unit::MagneticFluxDensity ); // Tesla (kg/s^2/A)
|
||||
const Quantity Quantity::Gauss ( 1e-4 , Unit::MagneticFluxDensity ); // 1 G = 1e-4 T
|
||||
|
||||
const Quantity Quantity::Tesla(1.0, Unit(0, 1, -2, -1)); // Tesla (kg/s^2/A)
|
||||
const Quantity Quantity::Gauss(1e-4, Unit(0, 1, -2, -1)); // 1 G = 1e-4 T
|
||||
const Quantity Quantity::Weber ( 1e6 , Unit::MagneticFlux ); // Weber (kg*m^2/s^2/A)
|
||||
|
||||
const Quantity Quantity::Weber(1e6, Unit(2, 1, -2, -1)); // Weber (kg*m^2/s^2/A)
|
||||
const Quantity Quantity::PicoFarad ( 1e-18 , Unit::ElectricalCapacitance );
|
||||
const Quantity Quantity::NanoFarad ( 1e-15 , Unit::ElectricalCapacitance );
|
||||
const Quantity Quantity::MicroFarad ( 1e-12 , Unit::ElectricalCapacitance );
|
||||
const Quantity Quantity::MilliFarad ( 1e-9 , Unit::ElectricalCapacitance );
|
||||
const Quantity Quantity::Farad ( 1e-6 , Unit::ElectricalCapacitance ); // Farad (s^4*A^2/m^2/kg)
|
||||
|
||||
// disable Oersted because people need to input e.g. a field strength of
|
||||
// 1 ampere per meter -> 1 A/m and not get the recalculation to Oersted
|
||||
// const Quantity Quantity::Oersted(0.07957747, Unit(-1, 0, 0, 1));// Oersted (A/m)
|
||||
const Quantity Quantity::NanoHenry ( 1e-3 , Unit::ElectricalInductance );
|
||||
const Quantity Quantity::MicroHenry ( 1.0 , Unit::ElectricalInductance );
|
||||
const Quantity Quantity::MilliHenry ( 1e+3 , Unit::ElectricalInductance );
|
||||
const Quantity Quantity::Henry ( 1e+6 , Unit::ElectricalInductance ); // Henry (kg*m^2/s^2/A^2)
|
||||
|
||||
const Quantity Quantity::PicoFarad(1e-18, Unit(-2, -1, 4, 2));
|
||||
const Quantity Quantity::NanoFarad(1e-15, Unit(-2, -1, 4, 2));
|
||||
const Quantity Quantity::MicroFarad(1e-12, Unit(-2, -1, 4, 2));
|
||||
const Quantity Quantity::MilliFarad(1e-9, Unit(-2, -1, 4, 2));
|
||||
const Quantity Quantity::Farad(1e-6, Unit(-2, -1, 4, 2)); // Farad (s^4*A^2/m^2/kg)
|
||||
const Quantity Quantity::Joule ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::MilliJoule ( 1e+3 , Unit::Moment );
|
||||
const Quantity Quantity::KiloJoule ( 1e+9 , Unit::Moment );
|
||||
const Quantity Quantity::NewtonMeter ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::VoltAmpereSecond ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::WattSecond ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::KiloWattHour ( 3.6e+12 , Unit::Moment ); // 1 kWh = 3.6e6 J
|
||||
const Quantity Quantity::ElectronVolt ( 1.602176634e-13 , Unit::Moment ); // 1 eV = 1.602176634e-19 J
|
||||
const Quantity Quantity::KiloElectronVolt ( 1.602176634e-10 , Unit::Moment );
|
||||
const Quantity Quantity::MegaElectronVolt ( 1.602176634e-7 , Unit::Moment );
|
||||
const Quantity Quantity::Calorie ( 4.1868e+6 , Unit::Moment ); // 1 cal = 4.1868 J
|
||||
const Quantity Quantity::KiloCalorie ( 4.1868e+9 , Unit::Moment );
|
||||
|
||||
const Quantity Quantity::NanoHenry(1e-3, Unit(2, 1, -2, -2));
|
||||
const Quantity Quantity::MicroHenry(1.0, Unit(2, 1, -2, -2));
|
||||
const Quantity Quantity::MilliHenry(1e+3, Unit(2, 1, -2, -2));
|
||||
const Quantity Quantity::Henry(1e+6, Unit(2, 1, -2, -2)); // Henry (kg*m^2/s^2/A^2)
|
||||
|
||||
const Quantity Quantity::Joule(1e+6, Unit(2, 1, -2)); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::MilliJoule(1e+3, Unit(2, 1, -2));
|
||||
const Quantity Quantity::KiloJoule(1e+9, Unit(2, 1, -2));
|
||||
const Quantity Quantity::NewtonMeter(1e+6, Unit(2, 1, -2)); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::VoltAmpereSecond(1e+6, Unit(2, 1, -2)); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::WattSecond(1e+6, Unit(2, 1, -2)); // Joule (kg*m^2/s^2)
|
||||
const Quantity Quantity::KiloWattHour(3.6e+12, Unit(2, 1, -2)); // 1 kWh = 3.6e6 J
|
||||
const Quantity Quantity::ElectronVolt(1.602176634e-13, Unit(2, 1, -2)); // 1 eV = 1.602176634e-19 J
|
||||
const Quantity Quantity::KiloElectronVolt(1.602176634e-10, Unit(2, 1, -2));
|
||||
const Quantity Quantity::MegaElectronVolt(1.602176634e-7, Unit(2, 1, -2));
|
||||
const Quantity Quantity::Calorie(4.1868e+6, Unit(2, 1, -2)); // 1 cal = 4.1868 J
|
||||
const Quantity Quantity::KiloCalorie(4.1868e+9, Unit(2, 1, -2));
|
||||
|
||||
const Quantity Quantity::KMH(277.778, Unit(1, 0, -1)); // km/h
|
||||
const Quantity Quantity::MPH(447.04, Unit(1, 0, -1)); // Mile/h
|
||||
|
||||
const Quantity Quantity::AngMinute(1.0 / 60.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // angular minute
|
||||
const Quantity Quantity::AngSecond(1.0 / 3600.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // angular second
|
||||
const Quantity
|
||||
Quantity::Degree(1.0,
|
||||
Unit(0, 0, 0, 0, 0, 0, 0, 1)); // degree (internal standard angle)
|
||||
const Quantity Quantity::Radian(180 / std::numbers::pi, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // radian
|
||||
const Quantity Quantity::Gon(360.0 / 400.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // gon
|
||||
const Quantity Quantity::KMH ( 277.778 , Unit::Velocity ); // km/h
|
||||
const Quantity Quantity::MPH ( 447.04 , Unit::Velocity ); // Mile/h
|
||||
|
||||
const Quantity Quantity::AngMinute ( 1.0 / 60.0 , Unit::Angle ); // angular minute
|
||||
const Quantity Quantity::AngSecond ( 1.0 / 3600.0 , Unit::Angle ); // angular second
|
||||
const Quantity Quantity::Degree ( 1.0 , Unit::Angle ); // degree (internal standard angle)
|
||||
const Quantity Quantity::Radian ( 180 / std::numbers::pi, Unit::Angle ); // radian
|
||||
const Quantity Quantity::Gon ( 360.0 / 400.0 , Unit::Angle ); // gon
|
||||
// clang-format on
|
||||
|
||||
// === Parser & Scanner stuff ===============================================
|
||||
|
||||
|
||||
@@ -191,12 +191,10 @@ public:
|
||||
double getValueAs(const Quantity&) const;
|
||||
|
||||
|
||||
/// true if it has a number without a unit
|
||||
/// true if it has no unit
|
||||
bool isDimensionless() const;
|
||||
/// true if it has a specific unit or no dimension.
|
||||
bool isDimensionlessOrUnit(const Unit& unit) const;
|
||||
/// true if it has a number and a valid unit
|
||||
bool isQuantity() const;
|
||||
/// true if it has a number with or without a unit
|
||||
bool isValid() const;
|
||||
/// sets the quantity invalid
|
||||
|
||||
@@ -43,19 +43,15 @@ using Base::Quantity;
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string QuantityPy::representation() const
|
||||
{
|
||||
std::stringstream ret;
|
||||
|
||||
double val = getQuantityPtr()->getValue();
|
||||
Unit unit = getQuantityPtr()->getUnit();
|
||||
|
||||
std::stringstream ss;
|
||||
// Use Python's implementation to repr() a float
|
||||
Py::Float flt(val);
|
||||
ret << static_cast<std::string>(flt.repr());
|
||||
if (!unit.isEmpty()) {
|
||||
ret << " " << unit.getString();
|
||||
Py::Float flt(getQuantityPtr()->getValue());
|
||||
ss << static_cast<std::string>(flt.repr());
|
||||
if (!getQuantityPtr()->isDimensionless()) {
|
||||
ss << " " << getQuantityPtr()->getUnit().getString();
|
||||
}
|
||||
|
||||
return ret.str();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
PyObject* QuantityPy::toStr(PyObject* args) const
|
||||
@@ -66,17 +62,16 @@ PyObject* QuantityPy::toStr(PyObject* args) const
|
||||
}
|
||||
|
||||
double val = getQuantityPtr()->getValue();
|
||||
Unit unit = getQuantityPtr()->getUnit();
|
||||
|
||||
std::stringstream ret;
|
||||
ret.precision(prec);
|
||||
ret.setf(std::ios::fixed, std::ios::floatfield);
|
||||
ret << val;
|
||||
if (!unit.isEmpty()) {
|
||||
ret << " " << unit.getString();
|
||||
std::stringstream ss;
|
||||
ss.precision(prec);
|
||||
ss.setf(std::ios::fixed, std::ios::floatfield);
|
||||
ss << val;
|
||||
if (!getQuantityPtr()->isDimensionless()) {
|
||||
ss << " " << getQuantityPtr()->getUnit().getString();
|
||||
}
|
||||
|
||||
return Py_BuildValue("s", ret.str().c_str());
|
||||
return Py_BuildValue("s", ss.str().c_str());
|
||||
}
|
||||
|
||||
PyObject* QuantityPy::PyMake(PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/)
|
||||
@@ -96,45 +91,37 @@ int QuantityPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
*self = *(static_cast<QuantityPy*>(object)->getQuantityPtr());
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
double f = std::numeric_limits<double>::max();
|
||||
if (PyArg_ParseTuple(args, "dO!", &f, &(UnitPy::Type), &object)) {
|
||||
*self = Quantity(f, *(static_cast<UnitPy*>(object)->getUnitPtr()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
if (PyArg_ParseTuple(args, "dO!", &f, &(QuantityPy::Type), &object)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Second argument must be a Unit not a Quantity");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
int i3 = 0;
|
||||
int i4 = 0;
|
||||
int i5 = 0;
|
||||
int i6 = 0;
|
||||
int i7 = 0;
|
||||
int i8 = 0;
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
int i1 {0};
|
||||
int i2 {0};
|
||||
int i3 {0};
|
||||
int i4 {0};
|
||||
int i5 {0};
|
||||
int i6 {0};
|
||||
int i7 {0};
|
||||
int i8 {0};
|
||||
if (PyArg_ParseTuple(args, "|diiiiiiii", &f, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8)) {
|
||||
if (f < std::numeric_limits<double>::max()) {
|
||||
*self = Quantity(f,
|
||||
Unit {static_cast<int8_t>(i1),
|
||||
static_cast<int8_t>(i2),
|
||||
static_cast<int8_t>(i3),
|
||||
static_cast<int8_t>(i4),
|
||||
static_cast<int8_t>(i5),
|
||||
static_cast<int8_t>(i6),
|
||||
static_cast<int8_t>(i7),
|
||||
static_cast<int8_t>(i8)});
|
||||
*self = Quantity {f, Unit(i1, i2, i3, i4, i5, i6, i7, i8)};
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
char* string {};
|
||||
if (PyArg_ParseTuple(args, "et", "utf-8", &string)) {
|
||||
std::string str(string);
|
||||
@@ -149,13 +136,13 @@ int QuantityPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
if (PyArg_ParseTuple(args, "det", &f, "utf-8", &string)) {
|
||||
std::string unit(string);
|
||||
std::string str(string);
|
||||
PyMem_Free(string);
|
||||
try {
|
||||
*self = Quantity(f, unit);
|
||||
*self = Quantity(f, str);
|
||||
}
|
||||
catch (const ParserError& e) {
|
||||
PyErr_SetString(PyExc_ValueError, e.what());
|
||||
@@ -215,7 +202,7 @@ PyObject* QuantityPy::getValueAs(PyObject* args) const
|
||||
};
|
||||
|
||||
auto tryUnitPartsAndValue = [&]() -> std::optional<Quantity> {
|
||||
double f = std::numeric_limits<double>::max();
|
||||
double f;
|
||||
int i1 {0};
|
||||
int i2 {0};
|
||||
int i3 {0};
|
||||
@@ -224,20 +211,11 @@ PyObject* QuantityPy::getValueAs(PyObject* args) const
|
||||
int i6 {0};
|
||||
int i7 {0};
|
||||
int i8 {0};
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "d|iiiiiiii", &f, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (f >= std::numeric_limits<double>::max()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto re = [](auto val) {
|
||||
return static_cast<int8_t>(val);
|
||||
};
|
||||
|
||||
return Quantity {f, Unit {re(i1), re(i2), re(i3), re(i4), re(i5), re(i6), re(i7), re(i8)}};
|
||||
return Quantity {f, Unit(i1, i2, i3, i4, i5, i6, i7, i8)};
|
||||
};
|
||||
|
||||
auto tryString = [&]() -> std::optional<Quantity> {
|
||||
@@ -279,11 +257,6 @@ PyObject* QuantityPy::getValueAs(PyObject* args) const
|
||||
}
|
||||
|
||||
const auto qpUnit = qPtr->getUnit();
|
||||
if (qpUnit.isEmpty()) {
|
||||
err("QuantityPtr returned empty unit");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const auto qUnit = quant.getUnit(); qUnit != qpUnit) {
|
||||
err("Unit mismatch (`" + qUnit.getString() + "` != `" + qpUnit.getString() + "`)");
|
||||
return false;
|
||||
@@ -301,7 +274,7 @@ PyObject* QuantityPy::getValueAs(PyObject* args) const
|
||||
}
|
||||
|
||||
const auto quant = optQuant.value();
|
||||
if (quant.isQuantity()) {
|
||||
if (!quant.isDimensionless()) {
|
||||
if (!checkQuant(quant)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
267
src/Base/Unit.h
267
src/Base/Unit.h
@@ -1,181 +1,178 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BASE_Unit_H
|
||||
#define BASE_Unit_H
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <FCGlobal.h>
|
||||
|
||||
#include "Exception.h"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
/**
|
||||
* The Unit class.
|
||||
*/
|
||||
class BaseExport Unit
|
||||
constexpr auto unitSymbols =
|
||||
std::to_array<std::string_view>({"mm", "kg", "s", "A", "K", "mol", "cd", "deg"});
|
||||
|
||||
constexpr auto unitNumExponents {unitSymbols.size()};
|
||||
using UnitExponents = std::array<int8_t, unitNumExponents>;
|
||||
|
||||
constexpr auto unitExponentLimit {8};
|
||||
|
||||
class BaseExport Unit final
|
||||
{
|
||||
public:
|
||||
/// default constructor
|
||||
explicit Unit(int8_t Length,
|
||||
int8_t Mass = 0,
|
||||
int8_t Time = 0,
|
||||
int8_t ElectricCurrent = 0,
|
||||
int8_t ThermodynamicTemperature = 0,
|
||||
int8_t AmountOfSubstance = 0,
|
||||
int8_t LuminousIntensity = 0,
|
||||
int8_t Angle = 0);
|
||||
Unit();
|
||||
Unit(const Unit&) = default;
|
||||
Unit(Unit&&) = default;
|
||||
explicit Unit(const std::string& expr);
|
||||
/// Destruction
|
||||
~Unit() = default;
|
||||
Unit() = default;
|
||||
|
||||
/** Operators. */
|
||||
//@{
|
||||
inline Unit& operator*=(const Unit& that);
|
||||
inline Unit& operator/=(const Unit& that);
|
||||
int operator[](int index) const;
|
||||
explicit constexpr Unit(const UnitExponents exps, const std::string_view name = "")
|
||||
: _exps {exps}
|
||||
, _name {name}
|
||||
{
|
||||
checkRange();
|
||||
}
|
||||
|
||||
/// helper constructor to ease Unit construction from Python
|
||||
explicit Unit(const int length,
|
||||
const int mass = 0,
|
||||
const int time = 0,
|
||||
const int electricCurrent = 0,
|
||||
const int thermodynamicTemperature = 0,
|
||||
const int amountOfSubstance = 0,
|
||||
const int luminousIntensity = 0,
|
||||
const int angle = 0);
|
||||
|
||||
bool operator==(const Unit&) const;
|
||||
bool operator!=(const Unit& that) const;
|
||||
Unit& operator*=(const Unit& that);
|
||||
Unit& operator/=(const Unit& that);
|
||||
Unit operator*(const Unit&) const;
|
||||
Unit operator/(const Unit&) const;
|
||||
bool operator==(const Unit&) const;
|
||||
bool operator!=(const Unit& that) const
|
||||
|
||||
[[nodiscard]] Unit pow(const double exp) const;
|
||||
[[nodiscard]] Unit root(const uint8_t num) const;
|
||||
|
||||
[[nodiscard]] UnitExponents exponents() const;
|
||||
[[nodiscard]] int length() const;
|
||||
|
||||
[[nodiscard]] std::string getString() const; // E.g. kg, mm^2, mm*kg/s^2
|
||||
[[nodiscard]] std::string getTypeString() const; // E.g. "Area", "Length", "Pressure"
|
||||
[[nodiscard]] std::string representation() const; // E.g. "Unit: mm (1,0,0,0,0,0,0,0) [Length]"
|
||||
|
||||
Unit sqrt() const
|
||||
{
|
||||
return !(*this == that);
|
||||
return root(2);
|
||||
}
|
||||
Unit cbrt() const
|
||||
{
|
||||
return root(3);
|
||||
}
|
||||
Unit& operator=(const Unit&) = default;
|
||||
Unit& operator=(Unit&&) = default;
|
||||
Unit pow(double exp) const;
|
||||
Unit sqrt() const;
|
||||
Unit cbrt() const;
|
||||
//@}
|
||||
int length() const;
|
||||
int mass() const;
|
||||
int time() const;
|
||||
int electricCurrent() const;
|
||||
int thermodynamicTemperature() const;
|
||||
int amountOfSubstance() const;
|
||||
int luminousIntensity() const;
|
||||
int angle() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
std::string getString() const;
|
||||
/// get the type as an string such as "Area", "Length" or "Pressure".
|
||||
std::string getTypeString() const;
|
||||
private:
|
||||
UnitExponents _exps {};
|
||||
std::string_view _name;
|
||||
|
||||
/** Predefined Unit types. */
|
||||
//@{
|
||||
/// Length unit
|
||||
static const Unit Length;
|
||||
/// Mass unit
|
||||
static const Unit Mass;
|
||||
constexpr void checkRange()
|
||||
{
|
||||
for (const auto exp : _exps) {
|
||||
if (exp >= unitExponentLimit) {
|
||||
throw OverflowError("Unit exponent overflow");
|
||||
}
|
||||
if (exp < -unitExponentLimit) {
|
||||
throw UnderflowError("Unit exponent underflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Angle
|
||||
/** Returns posIndexes, negIndexes*/
|
||||
std::pair<std::vector<size_t>, std::vector<size_t>> nonZeroValsIndexes() const;
|
||||
|
||||
public:
|
||||
static const Unit Acceleration;
|
||||
static const Unit AmountOfSubstance;
|
||||
static const Unit Angle;
|
||||
static const Unit AngleOfFriction;
|
||||
|
||||
static const Unit Density;
|
||||
|
||||
static const Unit Area;
|
||||
static const Unit Volume;
|
||||
static const Unit TimeSpan;
|
||||
static const Unit Frequency;
|
||||
static const Unit Velocity;
|
||||
static const Unit Acceleration;
|
||||
static const Unit Temperature;
|
||||
|
||||
static const Unit CompressiveStrength;
|
||||
static const Unit CurrentDensity;
|
||||
static const Unit Density;
|
||||
static const Unit DissipationRate;
|
||||
static const Unit DynamicViscosity;
|
||||
static const Unit ElectricalCapacitance;
|
||||
static const Unit ElectricalConductance;
|
||||
static const Unit ElectricalConductivity;
|
||||
static const Unit ElectricalInductance;
|
||||
static const Unit ElectricalResistance;
|
||||
static const Unit ElectricCharge;
|
||||
static const Unit ElectricCurrent;
|
||||
static const Unit ElectricPotential;
|
||||
static const Unit ElectricCharge;
|
||||
static const Unit SurfaceChargeDensity;
|
||||
static const Unit VolumeChargeDensity;
|
||||
static const Unit ElectromagneticPotential;
|
||||
static const Unit Force;
|
||||
static const Unit Frequency;
|
||||
static const Unit HeatFlux;
|
||||
static const Unit InverseArea;
|
||||
static const Unit InverseLength;
|
||||
static const Unit InverseVolume;
|
||||
static const Unit KinematicViscosity;
|
||||
static const Unit Length;
|
||||
static const Unit LuminousIntensity;
|
||||
static const Unit MagneticFieldStrength;
|
||||
static const Unit MagneticFlux;
|
||||
static const Unit MagneticFluxDensity;
|
||||
static const Unit Magnetization;
|
||||
static const Unit ElectricalCapacitance;
|
||||
static const Unit ElectricalInductance;
|
||||
static const Unit ElectricalConductance;
|
||||
static const Unit ElectricalResistance;
|
||||
static const Unit ElectricalConductivity;
|
||||
static const Unit ElectromagneticPotential;
|
||||
static const Unit AmountOfSubstance;
|
||||
static const Unit LuminousIntensity;
|
||||
|
||||
// Pressure
|
||||
static const Unit CompressiveStrength;
|
||||
static const Unit Mass;
|
||||
static const Unit Moment;
|
||||
static const Unit One;
|
||||
static const Unit Pressure;
|
||||
static const Unit Power;
|
||||
static const Unit ShearModulus;
|
||||
static const Unit Stress;
|
||||
static const Unit UltimateTensileStrength;
|
||||
static const Unit YieldStrength;
|
||||
static const Unit YoungsModulus;
|
||||
|
||||
static const Unit SpecificEnergy;
|
||||
static const Unit SpecificHeat;
|
||||
static const Unit Stiffness;
|
||||
static const Unit StiffnessDensity;
|
||||
|
||||
static const Unit Force;
|
||||
static const Unit Work;
|
||||
static const Unit Power;
|
||||
static const Unit Moment;
|
||||
|
||||
static const Unit SpecificEnergy;
|
||||
static const Unit Stress;
|
||||
static const Unit SurfaceChargeDensity;
|
||||
static const Unit Temperature;
|
||||
static const Unit TimeSpan;
|
||||
static const Unit ThermalConductivity;
|
||||
static const Unit ThermalExpansionCoefficient;
|
||||
static const Unit VolumetricThermalExpansionCoefficient;
|
||||
static const Unit SpecificHeat;
|
||||
static const Unit ThermalTransferCoefficient;
|
||||
static const Unit HeatFlux;
|
||||
static const Unit DynamicViscosity;
|
||||
static const Unit KinematicViscosity;
|
||||
static const Unit UltimateTensileStrength;
|
||||
static const Unit VacuumPermittivity;
|
||||
static const Unit Velocity;
|
||||
static const Unit Volume;
|
||||
static const Unit VolumeChargeDensity;
|
||||
static const Unit VolumeFlowRate;
|
||||
static const Unit DissipationRate;
|
||||
|
||||
static const Unit InverseLength;
|
||||
static const Unit InverseArea;
|
||||
static const Unit InverseVolume;
|
||||
|
||||
//@}
|
||||
private:
|
||||
uint32_t Val;
|
||||
static const Unit VolumetricThermalExpansionCoefficient;
|
||||
static const Unit Work;
|
||||
static const Unit YieldStrength;
|
||||
static const Unit YoungsModulus;
|
||||
};
|
||||
|
||||
inline Unit& Unit::operator*=(const Unit& that)
|
||||
{
|
||||
*this = *this * that;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Unit& Unit::operator/=(const Unit& that)
|
||||
{
|
||||
*this = *this / that;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace Base
|
||||
|
||||
#endif // BASE_Unit_H
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
#endif
|
||||
|
||||
#include "Unit.h"
|
||||
|
||||
@@ -35,25 +39,7 @@ using namespace Base;
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string UnitPy::representation() const
|
||||
{
|
||||
std::stringstream ret;
|
||||
Unit* self = getUnitPtr();
|
||||
|
||||
ret << "Unit: ";
|
||||
ret << self->getString() << " (";
|
||||
ret << (*self).length() << ",";
|
||||
ret << (*self).mass() << ",";
|
||||
ret << (*self).time() << ",";
|
||||
ret << (*self).electricCurrent() << ",";
|
||||
ret << (*self).thermodynamicTemperature() << ",";
|
||||
ret << (*self).amountOfSubstance() << ",";
|
||||
ret << (*self).luminousIntensity() << ",";
|
||||
ret << (*self).angle() << ")";
|
||||
|
||||
std::string type = self->getTypeString();
|
||||
if (!type.empty()) {
|
||||
ret << " [" << type << "]";
|
||||
}
|
||||
return ret.str();
|
||||
return getUnitPtr()->representation();
|
||||
}
|
||||
|
||||
PyObject* UnitPy::PyMake(PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/)
|
||||
@@ -98,14 +84,14 @@ int UnitPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
}
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
int i3 = 0;
|
||||
int i4 = 0;
|
||||
int i5 = 0;
|
||||
int i6 = 0;
|
||||
int i7 = 0;
|
||||
int i8 = 0;
|
||||
int i1 {0};
|
||||
int i2 {0};
|
||||
int i3 {0};
|
||||
int i4 {0};
|
||||
int i5 {0};
|
||||
int i6 {0};
|
||||
int i7 {0};
|
||||
int i8 {0};
|
||||
if (PyArg_ParseTuple(args, "|iiiiiiii", &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8)) {
|
||||
try {
|
||||
*self = Unit(i1, i2, i3, i4, i5, i6, i7, i8);
|
||||
@@ -115,6 +101,10 @@ int UnitPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
PyErr_SetString(PyExc_OverflowError, e.what());
|
||||
return -1;
|
||||
}
|
||||
catch (const UnderflowError& e) {
|
||||
PyErr_SetString(PyExc_OverflowError, e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Either string, (float,8 ints), Unit() or Quantity()");
|
||||
@@ -213,13 +203,11 @@ Py::String UnitPy::getType() const
|
||||
|
||||
Py::Tuple UnitPy::getSignature() const
|
||||
{
|
||||
Py::Tuple tuple(8);
|
||||
Unit* self = getUnitPtr();
|
||||
|
||||
for (auto i = 0; i < tuple.size(); i++) {
|
||||
tuple.setItem(i, Py::Long((*self)[i]));
|
||||
}
|
||||
|
||||
Py::Tuple tuple {unitNumExponents};
|
||||
auto exps = getUnitPtr()->exponents();
|
||||
std::ranges::for_each(exps, [&, pos {0}](auto exp) mutable {
|
||||
tuple.setItem(pos++, Py::Long {exp});
|
||||
});
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,22 +53,20 @@ std::string UnitsSchema::translate(const Quantity& quant) const
|
||||
std::string
|
||||
UnitsSchema::translate(const Quantity& quant, double& factor, std::string& unitString) const
|
||||
{
|
||||
// Use defaults without schema-level translation.
|
||||
factor = 1.0;
|
||||
unitString = quant.getUnit().getString();
|
||||
|
||||
if (spec.translationSpecs.empty()) {
|
||||
return toLocale(quant, 1.0, unitString);
|
||||
return toLocale(quant, factor, unitString);
|
||||
}
|
||||
|
||||
const auto unitName = quant.getUnit().getTypeString();
|
||||
|
||||
if (spec.translationSpecs.count(unitName) == 0) {
|
||||
// no schema-level translation. Use defaults.
|
||||
factor = 1.0;
|
||||
unitString = quant.getUnit().getString();
|
||||
|
||||
if (!spec.translationSpecs.contains(unitName)) {
|
||||
return toLocale(quant, factor, unitString);
|
||||
}
|
||||
|
||||
const auto value = quant.getValue();
|
||||
|
||||
auto isSuitable = [&](const UnitTranslationSpec& row) {
|
||||
return row.threshold > value || row.threshold == 0; // zero indicates default
|
||||
};
|
||||
@@ -81,7 +79,7 @@ UnitsSchema::translate(const Quantity& quant, double& factor, std::string& unitS
|
||||
}
|
||||
|
||||
if (unitSpec->factor == 0) {
|
||||
return UnitsSchemasData::runSpecial(unitSpec->unitString, value);
|
||||
return UnitsSchemasData::runSpecial(unitSpec->unitString, value, factor, unitString);
|
||||
}
|
||||
|
||||
factor = unitSpec->factor;
|
||||
@@ -96,20 +94,17 @@ UnitsSchema::toLocale(const Quantity& quant, const double factor, const std::str
|
||||
QLocale Lc;
|
||||
const QuantityFormat& format = quant.getFormat();
|
||||
if (format.option != QuantityFormat::None) {
|
||||
int opt = format.option;
|
||||
Lc.setNumberOptions(static_cast<QLocale::NumberOptions>(opt));
|
||||
Lc.setNumberOptions(static_cast<QLocale::NumberOptions>(format.option));
|
||||
}
|
||||
|
||||
std::string valueString =
|
||||
Lc.toString((quant.getValue() / factor), format.toFormat(), format.precision).toStdString();
|
||||
auto valueString =
|
||||
Lc.toString(quant.getValue() / factor, format.toFormat(), format.precision).toStdString();
|
||||
|
||||
return fmt::format("{}{}{}",
|
||||
valueString,
|
||||
unitString.empty() || unitString == "°" || unitString == "″"
|
||||
|| unitString == "′" || unitString == "\"" || unitString == "'"
|
||||
? ""
|
||||
: " ",
|
||||
unitString);
|
||||
auto notUnit = [](auto s) {
|
||||
return s.empty() || s == "°" || s == "″" || s == "′" || s == "\"" || s == "'";
|
||||
};
|
||||
|
||||
return fmt::format("{}{}{}", valueString, notUnit(unitString) ? "" : " ", unitString);
|
||||
}
|
||||
|
||||
bool UnitsSchema::isMultiUnitLength() const
|
||||
|
||||
@@ -733,17 +733,27 @@ inline std::string toDms(const double value)
|
||||
* Special functions caller
|
||||
*/
|
||||
|
||||
inline const std::map<std::string, std::function<std::string(double)>> specials // clang-format off
|
||||
// clang-format off
|
||||
inline const std::map<std::string, std::function<std::string(double, double&, std::string&)>> specials
|
||||
{
|
||||
{
|
||||
{ "toDMS" , [](const double val) { return toDms(val); }},
|
||||
{ "toFractional" , [](const double val) { return toFractional(val); }}
|
||||
{ "toDMS" , [](const double val, double& factor, std::string& unitString) {
|
||||
factor = 1.0;
|
||||
unitString = "deg";
|
||||
return toDms(val);
|
||||
}},
|
||||
{ "toFractional" , [](const double val, double& factor, std::string& unitString) {
|
||||
factor = 25.4;
|
||||
unitString = "in";
|
||||
return toFractional(val);
|
||||
}}
|
||||
}
|
||||
}; // clang-format on
|
||||
|
||||
inline std::string runSpecial(const std::string& name, const double value)
|
||||
inline std::string
|
||||
runSpecial(const std::string& name, const double value, double& factor, std::string& unitString)
|
||||
{
|
||||
return specials.contains(name) ? specials.at(name)(value) : "";
|
||||
return specials.contains(name) ? specials.at(name)(value, factor, unitString) : "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -298,14 +298,14 @@ void DlgExpressionInput::checkExpression(const QString& text)
|
||||
}
|
||||
|
||||
auto msg = value.getUserString();
|
||||
if (!impliedUnit.isEmpty()) {
|
||||
if (!value.getUnit().isEmpty() && value.getUnit() != impliedUnit)
|
||||
if (impliedUnit != Base::Unit::One) {
|
||||
if (!value.isDimensionless() && value.getUnit() != impliedUnit)
|
||||
throw Base::UnitsMismatchError("Unit mismatch between result and required unit");
|
||||
|
||||
value.setUnit(impliedUnit);
|
||||
|
||||
}
|
||||
else if (!value.getUnit().isEmpty()) {
|
||||
else if (!value.isDimensionless()) {
|
||||
msg += " (Warning: unit discarded)";
|
||||
|
||||
QPalette p(ui->msg->palette());
|
||||
|
||||
@@ -30,9 +30,13 @@
|
||||
|
||||
#include "Dialogs/DlgUnitsCalculatorImp.h"
|
||||
#include "ui_DlgUnitsCalculator.h"
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
using Base::Quantity;
|
||||
using Base::Unit;
|
||||
using Base::UnitsApi;
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DlgUnitsCalculator */
|
||||
|
||||
@@ -55,7 +59,7 @@ DlgUnitsCalculator::DlgUnitsCalculator(QWidget* parent, Qt::WindowFlags fl)
|
||||
auto addItem = [&, index {0}](const auto& item) mutable {
|
||||
ui->comboBoxScheme->addItem(QString::fromStdString(item), index++);
|
||||
};
|
||||
auto descriptions = Base::UnitsApi::getDescriptions();
|
||||
auto descriptions = UnitsApi::getDescriptions();
|
||||
std::for_each(descriptions.begin(), descriptions.end(), addItem);
|
||||
|
||||
// clang-format off
|
||||
@@ -65,7 +69,7 @@ DlgUnitsCalculator::DlgUnitsCalculator(QWidget* parent, Qt::WindowFlags fl)
|
||||
this, &DlgUnitsCalculator::onComboBoxSchemeActivated);
|
||||
connect(ui->spinBoxDecimals, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &DlgUnitsCalculator::onSpinBoxDecimalsValueChanged);
|
||||
connect(ui->ValueInput, qOverload<const Base::Quantity&>(&InputField::valueChanged),
|
||||
connect(ui->ValueInput, qOverload<const Quantity&>(&InputField::valueChanged),
|
||||
this, &DlgUnitsCalculator::valueChanged);
|
||||
connect(ui->ValueInput, &InputField::returnPressed,
|
||||
this, &DlgUnitsCalculator::returnPressed);
|
||||
@@ -86,31 +90,27 @@ DlgUnitsCalculator::DlgUnitsCalculator(QWidget* parent, Qt::WindowFlags fl)
|
||||
ui->ValueInput->setText(QStringLiteral("1 cm"));
|
||||
ui->UnitInput->setText(QStringLiteral("in"));
|
||||
|
||||
units << Base::Unit::Acceleration << Base::Unit::AmountOfSubstance << Base::Unit::Angle
|
||||
<< Base::Unit::Area << Base::Unit::Density << Base::Unit::CurrentDensity
|
||||
<< Base::Unit::DissipationRate << Base::Unit::DynamicViscosity
|
||||
<< Base::Unit::ElectricalCapacitance << Base::Unit::ElectricalInductance
|
||||
<< Base::Unit::ElectricalConductance << Base::Unit::ElectricalResistance
|
||||
<< Base::Unit::ElectricalConductivity << Base::Unit::ElectricCharge
|
||||
<< Base::Unit::ElectricCurrent << Base::Unit::ElectricPotential << Base::Unit::Force
|
||||
<< Base::Unit::Frequency << Base::Unit::HeatFlux << Base::Unit::InverseArea
|
||||
<< Base::Unit::InverseLength << Base::Unit::InverseVolume
|
||||
<< Base::Unit::KinematicViscosity << Base::Unit::Length << Base::Unit::LuminousIntensity
|
||||
<< Base::Unit::Mass << Base::Unit::MagneticFieldStrength << Base::Unit::MagneticFlux
|
||||
<< Base::Unit::MagneticFluxDensity << Base::Unit::Magnetization << Base::Unit::Power
|
||||
<< Base::Unit::Pressure << Base::Unit::SpecificEnergy << Base::Unit::SpecificHeat
|
||||
<< Base::Unit::Stiffness << Base::Unit::Temperature << Base::Unit::ThermalConductivity
|
||||
<< Base::Unit::ThermalExpansionCoefficient << Base::Unit::ThermalTransferCoefficient
|
||||
<< Base::Unit::TimeSpan << Base::Unit::VacuumPermittivity << Base::Unit::Velocity
|
||||
<< Base::Unit::Volume << Base::Unit::VolumeFlowRate
|
||||
<< Base::Unit::VolumetricThermalExpansionCoefficient << Base::Unit::Work;
|
||||
for (const Base::Unit& it : units) {
|
||||
units << Unit::Acceleration << Unit::AmountOfSubstance << Unit::Angle << Unit::Area
|
||||
<< Unit::Density << Unit::CurrentDensity << Unit::DissipationRate
|
||||
<< Unit::DynamicViscosity << Unit::ElectricalCapacitance << Unit::ElectricalInductance
|
||||
<< Unit::ElectricalConductance << Unit::ElectricalResistance
|
||||
<< Unit::ElectricalConductivity << Unit::ElectricCharge << Unit::ElectricCurrent
|
||||
<< Unit::ElectricPotential << Unit::Force << Unit::Frequency << Unit::HeatFlux
|
||||
<< Unit::InverseArea << Unit::InverseLength << Unit::InverseVolume
|
||||
<< Unit::KinematicViscosity << Unit::Length << Unit::LuminousIntensity << Unit::Mass
|
||||
<< Unit::MagneticFieldStrength << Unit::MagneticFlux << Unit::MagneticFluxDensity
|
||||
<< Unit::Magnetization << Unit::Power << Unit::Pressure << Unit::SpecificEnergy
|
||||
<< Unit::SpecificHeat << Unit::Stiffness << Unit::Temperature << Unit::ThermalConductivity
|
||||
<< Unit::ThermalExpansionCoefficient << Unit::ThermalTransferCoefficient << Unit::TimeSpan
|
||||
<< Unit::VacuumPermittivity << Unit::Velocity << Unit::Volume << Unit::VolumeFlowRate
|
||||
<< Unit::VolumetricThermalExpansionCoefficient << Unit::Work;
|
||||
for (const Unit& it : units) {
|
||||
ui->unitsBox->addItem(QString::fromStdString(it.getTypeString()));
|
||||
}
|
||||
|
||||
ui->quantitySpinBox->setValue(1.0);
|
||||
ui->quantitySpinBox->setUnit(units.front());
|
||||
ui->spinBoxDecimals->setValue(Base::UnitsApi::getDecimals());
|
||||
ui->spinBoxDecimals->setValue(UnitsApi::getDecimals());
|
||||
}
|
||||
|
||||
/** Destroys the object and frees any allocated resources */
|
||||
@@ -132,27 +132,32 @@ void DlgUnitsCalculator::textChanged(QString unit)
|
||||
valueChanged(actValue);
|
||||
}
|
||||
|
||||
void DlgUnitsCalculator::valueChanged(const Base::Quantity& quant)
|
||||
void DlgUnitsCalculator::valueChanged(const Quantity& quant)
|
||||
{
|
||||
std::string unitTypeStr;
|
||||
try {
|
||||
unitTypeStr =
|
||||
Quantity::parse(ui->UnitInput->text().toStdString()).getUnit().getTypeString();
|
||||
}
|
||||
catch (const Base::ParserError&) {
|
||||
}
|
||||
// first check the unit, if it is invalid, getTypeString() outputs an empty string
|
||||
// explicitly check for "ee" like in "eeV" because this would trigger an exception in Base::Unit
|
||||
// explicitly check for "ee" like in "eeV" because this would trigger an exception in Unit
|
||||
// since it expects then a scientific notation number like "1e3"
|
||||
if ((ui->UnitInput->text().mid(0, 2) == QStringLiteral("ee"))
|
||||
|| Base::Unit(ui->UnitInput->text().toStdString()).getTypeString().empty()) {
|
||||
if ((ui->UnitInput->text().mid(0, 2) == QStringLiteral("ee")) || unitTypeStr.empty()) {
|
||||
ui->ValueOutput->setText(
|
||||
QStringLiteral("%1 %2").arg(tr("unknown unit:"), ui->UnitInput->text()));
|
||||
ui->pushButton_Copy->setEnabled(false);
|
||||
}
|
||||
else { // the unit is valid
|
||||
// we can only convert units of the same type, thus check
|
||||
if (Base::Unit(ui->UnitInput->text().toStdString()).getTypeString()
|
||||
!= quant.getUnit().getTypeString()) {
|
||||
if (unitTypeStr != quant.getUnit().getTypeString()) {
|
||||
ui->ValueOutput->setText(tr("unit mismatch"));
|
||||
ui->pushButton_Copy->setEnabled(false);
|
||||
}
|
||||
else { // the unit is valid and has the same type
|
||||
double convertValue =
|
||||
Base::Quantity::parse("1" + ui->UnitInput->text().toStdString()).getValue();
|
||||
Quantity::parse("1" + ui->UnitInput->text().toStdString()).getValue();
|
||||
// we got now e.g. for "1 in" the value '25.4' because 1 in = 25.4 mm
|
||||
// the result is now just quant / convertValue because the input is always in a base
|
||||
// unit (an input of "1 cm" will immediately be converted to "10 mm" by Gui::InputField
|
||||
@@ -164,7 +169,7 @@ void DlgUnitsCalculator::valueChanged(const Base::Quantity& quant)
|
||||
// "10 um" in "in", thus only if value > 0.005 because FC's default are 2 decimals
|
||||
QString val = QLocale().toString(value, 'g');
|
||||
if (!val.contains(QChar::fromLatin1('e')) && (value > 0.005)) {
|
||||
val = QLocale().toString(value, 'f', Base::UnitsApi::getDecimals());
|
||||
val = QLocale().toString(value, 'f', UnitsApi::getDecimals());
|
||||
}
|
||||
// create the output string
|
||||
QString out = QStringLiteral("%1 %2").arg(val, ui->UnitInput->text());
|
||||
@@ -201,13 +206,13 @@ void DlgUnitsCalculator::onUnitsBoxActivated(int index)
|
||||
{
|
||||
// SI units use [m], not [mm] for lengths
|
||||
//
|
||||
Base::Quantity q = ui->quantitySpinBox->value();
|
||||
Quantity q = ui->quantitySpinBox->value();
|
||||
int32_t old = q.getUnit().length();
|
||||
double value = q.getValue();
|
||||
|
||||
Base::Unit unit = units[index];
|
||||
Unit unit = units[index];
|
||||
int32_t len = unit.length();
|
||||
ui->quantitySpinBox->setValue(Base::Quantity(value * std::pow(10.0, 3 * (len - old)), unit));
|
||||
ui->quantitySpinBox->setValue(Quantity(value * std::pow(10.0, 3 * (len - old)), unit));
|
||||
}
|
||||
|
||||
void DlgUnitsCalculator::onComboBoxSchemeActivated(int index)
|
||||
|
||||
@@ -278,11 +278,11 @@ void InputField::newInput(const QString & text)
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.getUnit().isEmpty())
|
||||
if (res.isDimensionless())
|
||||
res.setUnit(this->actUnit);
|
||||
|
||||
// check if unit fits!
|
||||
if(!actUnit.isEmpty() && !res.getUnit().isEmpty() && actUnit != res.getUnit()){
|
||||
if (actUnit != Unit::One && !res.isDimensionless() && actUnit != res.getUnit()){
|
||||
if (iconLabel->isHidden()) {
|
||||
iconLabel->setVisible(true);
|
||||
}
|
||||
@@ -644,7 +644,7 @@ void InputField::focusInEvent(QFocusEvent *event)
|
||||
void InputField::focusOutEvent(QFocusEvent *event)
|
||||
{
|
||||
try {
|
||||
if (Quantity::parse(this->text().toStdString()).getUnit().isEmpty()) {
|
||||
if (Quantity::parse(this->text().toStdString()).isDimensionless()) {
|
||||
// if user didn't enter a unit, we virtually compensate
|
||||
// the multiplication factor induced by user unit system
|
||||
double factor;
|
||||
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
ok = parseString(copy, res, value, path);
|
||||
|
||||
// If result does not have unit: add default unit
|
||||
if (res.getUnit().isEmpty()){
|
||||
if (res.isDimensionless()) {
|
||||
res.setUnit(unit);
|
||||
}
|
||||
|
||||
|
||||
@@ -1786,15 +1786,11 @@ void PropertyVectorDistanceItem::setValue(const QVariant& variant)
|
||||
}
|
||||
const Base::Vector3d& value = variant.value<Base::Vector3d>();
|
||||
|
||||
Base::Quantity x = Base::Quantity(value.x, Base::Unit::Length);
|
||||
Base::Quantity y = Base::Quantity(value.y, Base::Unit::Length);
|
||||
Base::Quantity z = Base::Quantity(value.z, Base::Unit::Length);
|
||||
|
||||
Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec);
|
||||
std::string val = fmt::format("({}, {}, {})",
|
||||
Base::UnitsApi::toNumber(x, format),
|
||||
Base::UnitsApi::toNumber(y, format),
|
||||
Base::UnitsApi::toNumber(z, format));
|
||||
Base::UnitsApi::toNumber(value.x, format),
|
||||
Base::UnitsApi::toNumber(value.y, format),
|
||||
Base::UnitsApi::toNumber(value.z, format));
|
||||
setPropertyValue(val);
|
||||
}
|
||||
|
||||
|
||||
@@ -611,12 +611,11 @@ Base::Unit FemPostPipeline::getFrameUnit()
|
||||
|
||||
vtkAbstractArray* TimeInfo = multiblock->GetFieldData()->GetAbstractArray("TimeInfo");
|
||||
if (!TimeInfo->IsA("vtkStringArray") || TimeInfo->GetNumberOfTuples() < 2) {
|
||||
|
||||
// units cannot be undefined, so use time
|
||||
return Base::Unit::TimeSpan;
|
||||
}
|
||||
|
||||
return Base::Unit(vtkStringArray::SafeDownCast(TimeInfo)->GetValue(1));
|
||||
auto qty = Base::Quantity(0, vtkStringArray::SafeDownCast(TimeInfo)->GetValue(1));
|
||||
return qty.getUnit();
|
||||
}
|
||||
|
||||
std::vector<double> FemPostPipeline::getFrameValues()
|
||||
|
||||
@@ -201,8 +201,8 @@ int EditDatumDialog::exec(bool atCursor)
|
||||
void EditDatumDialog::accepted()
|
||||
{
|
||||
Base::Quantity newQuant = ui_ins_datum->labelEdit->value();
|
||||
if (newQuant.isQuantity() || (Constr->Type == Sketcher::SnellsLaw && newQuant.isDimensionless())
|
||||
|| (Constr->Type == Sketcher::Weight && newQuant.isDimensionless())) {
|
||||
if (Constr->Type == Sketcher::SnellsLaw || Constr->Type == Sketcher::Weight
|
||||
|| !newQuant.isDimensionless()) {
|
||||
|
||||
// save the value for the history
|
||||
ui_ins_datum->labelEdit->pushToHistory();
|
||||
|
||||
@@ -607,7 +607,7 @@ void Cell::setComputedUnit(const Base::Unit& unit)
|
||||
PropertySheet::AtomicPropertyChange signaller(*owner);
|
||||
|
||||
computedUnit = unit;
|
||||
setUsed(COMPUTED_UNIT_SET, !computedUnit.isEmpty());
|
||||
setUsed(COMPUTED_UNIT_SET, computedUnit != Unit::One);
|
||||
setDirty();
|
||||
|
||||
signaller.tryInvoke();
|
||||
@@ -1110,7 +1110,7 @@ std::string Cell::getFormattedQuantity()
|
||||
const Base::Unit& computedUnit = floatProp->getUnit();
|
||||
qFormatted = QLocale().toString(rawVal, 'f', Base::UnitsApi::getDecimals());
|
||||
if (hasDisplayUnit) {
|
||||
if (computedUnit.isEmpty() || computedUnit == du.unit) {
|
||||
if (computedUnit == Unit::One || computedUnit == du.unit) {
|
||||
QString number =
|
||||
QLocale().toString(rawVal / duScale, 'f', Base::UnitsApi::getDecimals());
|
||||
qFormatted = number + QString::fromStdString(" " + displayUnit.stringRep);
|
||||
|
||||
@@ -802,7 +802,7 @@ void Sheet::updateProperty(CellAddress key)
|
||||
Base::PyGILStateLocker lock;
|
||||
setObjectProperty(key, constant->getPyValue());
|
||||
}
|
||||
else if (!number->getUnit().isEmpty()) {
|
||||
else if (number->getUnit() != Unit::One) {
|
||||
setQuantityProperty(key, number->getValue(), number->getUnit());
|
||||
}
|
||||
else if (number->isInteger(&l)) {
|
||||
|
||||
@@ -384,7 +384,7 @@ QVariant SheetModel::data(const QModelIndex& index, int role) const
|
||||
|
||||
// Display locale specific decimal separator (#0003875,#0003876)
|
||||
if (cell->getDisplayUnit(displayUnit)) {
|
||||
if (computedUnit.isEmpty() || computedUnit == displayUnit.unit) {
|
||||
if (computedUnit == Base::Unit::One || computedUnit == displayUnit.unit) {
|
||||
QString number =
|
||||
QLocale().toString(floatProp->getValue() / displayUnit.scaler,
|
||||
'f',
|
||||
|
||||
@@ -37,16 +37,12 @@ protected:
|
||||
App::DocumentObject* this_obj() { return _this_obj; }
|
||||
|
||||
Base::Quantity parse_expression_text_as_quantity(const char* expression_text) {
|
||||
auto expression = App::ExpressionParser::parse(this_obj(), expression_text);
|
||||
auto expression_value = expression->getValueAsAny();
|
||||
auto quantity_result = App::any_cast<Base::Quantity>(expression_value);
|
||||
return quantity_result;
|
||||
const auto expression = App::ExpressionParser::parse(this_obj(), expression_text);
|
||||
return App::any_cast<Base::Quantity>(expression->getValueAsAny());
|
||||
}
|
||||
|
||||
Base::Quantity parse_quantity_text_as_quantity(const char* quantity_text) {
|
||||
auto quantity_str = std::string(quantity_text);
|
||||
auto quantity_result = Base::Quantity::parse(quantity_str);
|
||||
return quantity_result;
|
||||
return Base::Quantity::parse(quantity_text);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -27,13 +27,6 @@ TEST(BaseQuantity, TestParse)
|
||||
EXPECT_THROW(auto rew [[maybe_unused]] = Quantity::parse("1,234,500.12 kg"), ParserError);
|
||||
}
|
||||
|
||||
TEST(BaseQuantity, TestDim)
|
||||
{
|
||||
const Quantity q1 {0, Unit::Area};
|
||||
|
||||
EXPECT_EQ(q1.isQuantity(), true);
|
||||
}
|
||||
|
||||
TEST(BaseQuantity, TestNoDim)
|
||||
{
|
||||
const Quantity q1 {};
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "Base/UnitsSchemas.h"
|
||||
|
||||
#include <QLocale>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
using Base::Quantity;
|
||||
@@ -76,6 +77,119 @@ protected:
|
||||
std::unique_ptr<UnitsSchemas> schemas; // NOLINT
|
||||
};
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_1_mm_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 1.0, Unit::Length, 6);
|
||||
const auto expect {"0.001000 m"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_15_mm2_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 15.0, Unit::Area, 6);
|
||||
const auto expect {"0.000015 m^2"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_123456000_mm3_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 123456000.0, Unit::Volume, 6);
|
||||
const auto expect {"0.123456 m^3"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_123456000_W_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 123456000.0, Unit::Power, 6);
|
||||
const auto expect {"123.456000 W"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_123456000_V_precision_6)
|
||||
{
|
||||
const std::string result =
|
||||
setWithPrecision("MeterDecimal", 123456000.0, Unit::ElectricPotential, 6);
|
||||
const auto expect {"123.456000 V"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_123456000_W_m2_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 123.456, Unit::HeatFlux, 6);
|
||||
const auto expect {"123.456000 W/m^2"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, meter_decimal_123456000_m_s_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MeterDecimal", 123.456, Unit::Velocity, 6);
|
||||
const auto expect {"0.123456 m/s"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_1_mm_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 1.0, Unit::Length, 6);
|
||||
const auto expect {"1.000000 mm"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_15_mm2_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 15.0, Unit::Area, 6);
|
||||
const auto expect {"15.000000 mm^2"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_123456000_mm3_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 123456000.0, Unit::Volume, 6);
|
||||
const auto expect {"123.456000 l"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_123456000_W_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 123456000.0, Unit::Power, 6);
|
||||
const auto expect {"123.456000 W"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_123456000_V_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 123456000.0, Unit::ElectricPotential, 6);
|
||||
const auto expect {"123.456000 V"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_123456000_W_m2_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 123.456, Unit::HeatFlux, 6);
|
||||
const auto expect {"123.456000 W/m^2"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, mks_123456000_m_s_precision_6)
|
||||
{
|
||||
const std::string result = setWithPrecision("MKS", 123.456, Unit::Velocity, 6);
|
||||
const auto expect {"0.123456 m/s"};
|
||||
|
||||
EXPECT_EQ(result, expect);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, imperial_decimal_1_mm_default_precision)
|
||||
{
|
||||
const std::string result = set("ImperialDecimal", Unit::Length, 1.0);
|
||||
@@ -410,3 +524,161 @@ TEST_F(SchemaTest, unknown_schema_name_throws)
|
||||
{
|
||||
EXPECT_THROW(UnitsApi::setSchema("Unknown"), RuntimeError);
|
||||
}
|
||||
|
||||
TEST_F(SchemaTest, round_trip_test)
|
||||
{
|
||||
const auto units = std::to_array<Unit>({
|
||||
Unit::Length,
|
||||
Unit::Mass,
|
||||
Unit::Area,
|
||||
Unit::Density,
|
||||
Unit::Volume,
|
||||
Unit::TimeSpan,
|
||||
Unit::Frequency,
|
||||
Unit::Velocity,
|
||||
Unit::Acceleration,
|
||||
Unit::Temperature,
|
||||
Unit::CurrentDensity,
|
||||
Unit::ElectricCurrent,
|
||||
Unit::ElectricPotential,
|
||||
Unit::ElectricCharge,
|
||||
Unit::SurfaceChargeDensity,
|
||||
Unit::MagneticFieldStrength,
|
||||
Unit::MagneticFlux,
|
||||
Unit::MagneticFluxDensity,
|
||||
Unit::Magnetization,
|
||||
Unit::ElectricalCapacitance,
|
||||
Unit::ElectricalInductance,
|
||||
Unit::ElectricalConductance,
|
||||
Unit::ElectricalResistance,
|
||||
Unit::ElectricalConductivity,
|
||||
Unit::ElectromagneticPotential,
|
||||
Unit::AmountOfSubstance,
|
||||
Unit::LuminousIntensity,
|
||||
Unit::CompressiveStrength,
|
||||
Unit::Pressure,
|
||||
Unit::ShearModulus,
|
||||
Unit::Stress,
|
||||
Unit::UltimateTensileStrength,
|
||||
Unit::YieldStrength,
|
||||
Unit::YoungsModulus,
|
||||
Unit::Stiffness,
|
||||
Unit::StiffnessDensity,
|
||||
Unit::Force,
|
||||
Unit::Work,
|
||||
Unit::Power,
|
||||
Unit::Moment,
|
||||
Unit::SpecificEnergy,
|
||||
Unit::ThermalConductivity,
|
||||
Unit::ThermalExpansionCoefficient,
|
||||
Unit::VolumetricThermalExpansionCoefficient,
|
||||
Unit::SpecificHeat,
|
||||
Unit::ThermalTransferCoefficient,
|
||||
Unit::HeatFlux,
|
||||
Unit::DynamicViscosity,
|
||||
Unit::KinematicViscosity,
|
||||
Unit::VacuumPermittivity,
|
||||
Unit::VolumeFlowRate,
|
||||
Unit::DissipationRate,
|
||||
Unit::InverseLength,
|
||||
Unit::InverseArea,
|
||||
Unit::InverseVolume,
|
||||
});
|
||||
|
||||
std::array values = {0.01, 0.1, 1.0, 10.0, 100.0};
|
||||
|
||||
double factor {};
|
||||
std::string unitString;
|
||||
|
||||
UnitsApi::setDecimals(16);
|
||||
|
||||
UnitsApi::setSchema("Internal");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("MKS");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("Imperial");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_NEAR(q2.getValue(), value, 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("ImperialDecimal");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_NEAR(q2.getValue(), value, 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("Centimeter");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("MmMin");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("ImperialCivil");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_NEAR(q2.getValue(), value, 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("FEM");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
UnitsApi::setSchema("MeterDecimal");
|
||||
for (auto unit : units) {
|
||||
for (double value : values) {
|
||||
Quantity q1 {value, unit};
|
||||
std::string result = UnitsApi::schemaTranslate(q1, factor, unitString);
|
||||
Quantity q2 = Quantity::parse(result);
|
||||
EXPECT_DOUBLE_EQ(q2.getValue(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,191 +3,154 @@
|
||||
#include <Base/Exception.h>
|
||||
|
||||
// NOLINTBEGIN
|
||||
TEST(Unit, TestString)
|
||||
using namespace Base;
|
||||
|
||||
TEST(Unit, string_simple_numerator_no_denominator)
|
||||
{
|
||||
auto toString = [](const Base::Unit& unit) {
|
||||
return unit.getString();
|
||||
};
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 0, 0, 0, 0, 0)), "");
|
||||
EXPECT_EQ(toString(Base::Unit(1, 0, 0, 0, 0, 0, 0, 0)), "mm");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 1, 0, 0, 0, 0, 0, 0)), "kg");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 1, 0, 0, 0, 0, 0)), "s");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 1, 0, 0, 0, 0)), "A");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 0, 1, 0, 0, 0)), "K");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 0, 0, 1, 0, 0)), "mol");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 0, 0, 0, 1, 0)), "cd");
|
||||
EXPECT_EQ(toString(Base::Unit(0, 0, 0, 0, 0, 0, 0, 1)), "deg");
|
||||
EXPECT_EQ(toString(Base::Unit(2, 0, 0, 0, 0, 0, 0, 0)), "mm^2");
|
||||
EXPECT_EQ(toString(Base::Unit(1, 1, -2, 0, 0, 0, 0, 0)), "mm*kg/s^2");
|
||||
EXPECT_EQ(Unit::Length.getString(), "mm");
|
||||
}
|
||||
|
||||
TEST(Unit, TestTypeString)
|
||||
TEST(Unit, string_complex_numerator_no_denominator)
|
||||
{
|
||||
auto toString = [](const Base::Unit& unit) {
|
||||
return unit.getTypeString();
|
||||
};
|
||||
EXPECT_EQ(toString(Base::Unit::Acceleration), "Acceleration");
|
||||
EXPECT_EQ(toString(Base::Unit::AmountOfSubstance), "AmountOfSubstance");
|
||||
EXPECT_EQ(toString(Base::Unit::Angle), "Angle");
|
||||
EXPECT_EQ(toString(Base::Unit::AngleOfFriction), "Angle"); // same unit as Angle
|
||||
EXPECT_EQ(toString(Base::Unit::Area), "Area");
|
||||
EXPECT_EQ(toString(Base::Unit::CurrentDensity), "CurrentDensity");
|
||||
EXPECT_EQ(toString(Base::Unit::Density), "Density");
|
||||
EXPECT_EQ(toString(Base::Unit::DissipationRate), "DissipationRate");
|
||||
EXPECT_EQ(toString(Base::Unit::DynamicViscosity), "DynamicViscosity");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricalCapacitance), "ElectricalCapacitance");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricalConductance), "ElectricalConductance");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricalConductivity), "ElectricalConductivity");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricalInductance), "ElectricalInductance");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricalResistance), "ElectricalResistance");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricCharge), "ElectricCharge");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricCurrent), "ElectricCurrent");
|
||||
EXPECT_EQ(toString(Base::Unit::ElectricPotential), "ElectricPotential");
|
||||
EXPECT_EQ(toString(Base::Unit::Frequency), "Frequency");
|
||||
EXPECT_EQ(toString(Base::Unit::Force), "Force");
|
||||
EXPECT_EQ(toString(Base::Unit::HeatFlux), "HeatFlux");
|
||||
EXPECT_EQ(toString(Base::Unit::InverseArea), "InverseArea");
|
||||
EXPECT_EQ(toString(Base::Unit::InverseLength), "InverseLength");
|
||||
EXPECT_EQ(toString(Base::Unit::InverseVolume), "InverseVolume");
|
||||
EXPECT_EQ(toString(Base::Unit::KinematicViscosity), "KinematicViscosity");
|
||||
EXPECT_EQ(toString(Base::Unit::Length), "Length");
|
||||
EXPECT_EQ(toString(Base::Unit::LuminousIntensity), "LuminousIntensity");
|
||||
EXPECT_EQ(toString(Base::Unit::MagneticFieldStrength), "MagneticFieldStrength");
|
||||
EXPECT_EQ(toString(Base::Unit::MagneticFlux), "MagneticFlux");
|
||||
EXPECT_EQ(toString(Base::Unit::MagneticFluxDensity), "MagneticFluxDensity");
|
||||
EXPECT_EQ(toString(Base::Unit::Magnetization),
|
||||
"MagneticFieldStrength"); // same as MagneticFieldStrength
|
||||
EXPECT_EQ(toString(Base::Unit::Mass), "Mass");
|
||||
EXPECT_EQ(toString(Base::Unit::Pressure), "Pressure");
|
||||
EXPECT_EQ(toString(Base::Unit::Power), "Power");
|
||||
EXPECT_EQ(toString(Base::Unit::ShearModulus), "Pressure"); // same as Pressure
|
||||
EXPECT_EQ(toString(Base::Unit::SpecificEnergy), "SpecificEnergy");
|
||||
EXPECT_EQ(toString(Base::Unit::SpecificHeat), "SpecificHeat");
|
||||
EXPECT_EQ(toString(Base::Unit::Stiffness), "Stiffness");
|
||||
EXPECT_EQ(toString(Base::Unit::Stress), "Pressure"); // same as Pressure
|
||||
EXPECT_EQ(toString(Base::Unit::Temperature), "Temperature");
|
||||
EXPECT_EQ(toString(Base::Unit::ThermalConductivity), "ThermalConductivity");
|
||||
EXPECT_EQ(toString(Base::Unit::ThermalExpansionCoefficient), "ThermalExpansionCoefficient");
|
||||
EXPECT_EQ(toString(Base::Unit::ThermalTransferCoefficient), "ThermalTransferCoefficient");
|
||||
EXPECT_EQ(toString(Base::Unit::TimeSpan), "TimeSpan");
|
||||
EXPECT_EQ(toString(Base::Unit::UltimateTensileStrength), "Pressure"); // same as Pressure
|
||||
EXPECT_EQ(toString(Base::Unit::VacuumPermittivity), "VacuumPermittivity");
|
||||
EXPECT_EQ(toString(Base::Unit::Velocity), "Velocity");
|
||||
EXPECT_EQ(toString(Base::Unit::Volume), "Volume");
|
||||
EXPECT_EQ(toString(Base::Unit::VolumeFlowRate), "VolumeFlowRate");
|
||||
EXPECT_EQ(toString(Base::Unit::VolumetricThermalExpansionCoefficient),
|
||||
"ThermalExpansionCoefficient");
|
||||
EXPECT_EQ(toString(Base::Unit::Work), "Work");
|
||||
EXPECT_EQ(toString(Base::Unit::YieldStrength), "Pressure"); // same as Pressure
|
||||
EXPECT_EQ(toString(Base::Unit::YoungsModulus), "Pressure"); // same unit as Pressure
|
||||
EXPECT_EQ(Unit::Area.getString(), "mm^2");
|
||||
}
|
||||
TEST(Unit, strings)
|
||||
|
||||
TEST(Unit, string_complex_single_denominator)
|
||||
{
|
||||
EXPECT_STREQ(Base::Unit::Acceleration.getString().c_str(), "mm/s^2");
|
||||
EXPECT_STREQ(Base::Unit::AmountOfSubstance.getString().c_str(), "mol");
|
||||
EXPECT_STREQ(Base::Unit::Angle.getString().c_str(), "deg");
|
||||
EXPECT_STREQ(Base::Unit::AngleOfFriction.getString().c_str(), "deg");
|
||||
EXPECT_STREQ(Base::Unit::Area.getString().c_str(), "mm^2");
|
||||
EXPECT_STREQ(Base::Unit::CurrentDensity.getString().c_str(), "A/mm^2");
|
||||
EXPECT_STREQ(Base::Unit::Density.getString().c_str(), "kg/mm^3");
|
||||
EXPECT_STREQ(Base::Unit::DissipationRate.getString().c_str(), "mm^2/s^3");
|
||||
EXPECT_EQ(Unit::DissipationRate.getString(), "mm^2/s^3");
|
||||
}
|
||||
|
||||
TEST(Unit, string_no_numerator)
|
||||
{
|
||||
EXPECT_EQ(Unit::InverseArea.getString(), "1/mm^2");
|
||||
}
|
||||
|
||||
TEST(Unit, string_complex_multi_denominator)
|
||||
{
|
||||
EXPECT_EQ(Unit::MagneticFlux.getString(), "mm^2*kg/(s^2*A)");
|
||||
}
|
||||
|
||||
TEST(Unit, type_string)
|
||||
{
|
||||
EXPECT_EQ(Unit::MagneticFlux.getTypeString(), "MagneticFlux");
|
||||
}
|
||||
|
||||
TEST(Unit, TestEqual)
|
||||
{
|
||||
Base::Unit unit {1};
|
||||
EXPECT_EQ(unit.pow(2) == Base::Unit {2}, true);
|
||||
EXPECT_TRUE(Unit::Length == Unit::Length);
|
||||
}
|
||||
|
||||
TEST(Unit, TestNotEqual)
|
||||
{
|
||||
Base::Unit unit {1};
|
||||
EXPECT_EQ(unit.pow(2) != Base::Unit {1}, true);
|
||||
EXPECT_TRUE(Unit::Length != Unit::Area);
|
||||
}
|
||||
|
||||
TEST(Unit, multiply_One_is_One)
|
||||
{
|
||||
EXPECT_EQ(Unit::One * Unit::One, Unit::One);
|
||||
}
|
||||
|
||||
TEST(Unit, TestMult)
|
||||
{
|
||||
EXPECT_EQ(Base::Unit {} * Base::Unit {}, Base::Unit {});
|
||||
EXPECT_EQ(Base::Unit(0, 1) * Base::Unit(1, 0), Base::Unit(1, 1));
|
||||
constexpr UnitExponents arr {1, 1, 0, 0, 0, 0, 0, 0};
|
||||
EXPECT_EQ(Unit::Mass * Unit::Length, Unit {arr});
|
||||
}
|
||||
|
||||
TEST(Unit, TestDiv)
|
||||
TEST(Unit, div)
|
||||
{
|
||||
EXPECT_EQ(Base::Unit {} * Base::Unit {}, Base::Unit {});
|
||||
EXPECT_EQ(Base::Unit(0, 1) / Base::Unit(1, 0), Base::Unit(-1, 1));
|
||||
EXPECT_EQ(Unit::Area / Unit::Length, Unit::Length);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPowNoDim)
|
||||
TEST(Unit, div_by_One_does_nothing)
|
||||
{
|
||||
Base::Unit unit {};
|
||||
EXPECT_EQ(unit.pow(2), Base::Unit {0});
|
||||
EXPECT_EQ(unit.isEmpty(), true);
|
||||
EXPECT_EQ(Unit::Area / Unit::One, Unit::Area);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPowEQ1)
|
||||
TEST(Unit, pow_0_is_One)
|
||||
{
|
||||
Base::Unit unit {2};
|
||||
EXPECT_EQ(unit.pow(1), Base::Unit {2});
|
||||
EXPECT_EQ(Unit::Area.pow(0), Unit::One);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPowEQ0)
|
||||
TEST(Unit, pow_1_leaves_unit_unchanged)
|
||||
{
|
||||
Base::Unit unit {2};
|
||||
EXPECT_EQ(unit.pow(0), Base::Unit {0});
|
||||
EXPECT_EQ(Unit::Area.pow(1), Unit::Area);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPowGT1)
|
||||
TEST(Unit, pow_2_is_squared)
|
||||
{
|
||||
Base::Unit unit {2};
|
||||
EXPECT_EQ(unit.pow(2), Base::Unit {4});
|
||||
EXPECT_EQ(Unit::Length.pow(2), Unit::Area);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPowLT1)
|
||||
TEST(Unit, pow_3_is_cubed)
|
||||
{
|
||||
Base::Unit unit {3};
|
||||
EXPECT_EQ(unit.pow(1.0 / 3.0), Base::Unit {1});
|
||||
EXPECT_EQ(Unit::Length.pow(3), Unit::Volume);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPow3DIV2)
|
||||
TEST(Unit, pow_less_than_one)
|
||||
{
|
||||
Base::Unit unit {3};
|
||||
EXPECT_THROW(unit.pow(3.0 / 2.0), Base::UnitsMismatchError);
|
||||
EXPECT_EQ(Unit::Volume.pow(1.0 / 3.0), Unit::Length);
|
||||
}
|
||||
|
||||
TEST(Unit, TestOverflow)
|
||||
TEST(Unit, one_still_one_after_pow)
|
||||
{
|
||||
// this tests _that_ the expected exception is thrown
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
Base::Unit unit {3};
|
||||
unit.pow(10000);
|
||||
}
|
||||
catch (const Base::OverflowError& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ("Unit overflow in pow()", e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
Base::OverflowError);
|
||||
EXPECT_EQ(Unit::One.pow(2), Unit::One);
|
||||
}
|
||||
|
||||
TEST(Unit, TestUnderflow)
|
||||
TEST(Unit, square_root)
|
||||
{
|
||||
// this tests _that_ the expected exception is thrown
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
Base::Unit unit {3};
|
||||
unit.pow(-10000);
|
||||
}
|
||||
catch (const Base::UnderflowError& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ("Unit underflow in pow()", e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
Base::UnderflowError);
|
||||
EXPECT_EQ(Unit::Area.root(2), Unit::Length);
|
||||
}
|
||||
|
||||
// NOLINTEND
|
||||
TEST(Unit, cube_root)
|
||||
{
|
||||
EXPECT_EQ(Unit::Volume.root(3), Unit::Length);
|
||||
}
|
||||
|
||||
TEST(Unit, zero_root)
|
||||
{
|
||||
EXPECT_THROW([[maybe_unused]] auto res = Unit::Area.root(0), UnitsMismatchError);
|
||||
}
|
||||
|
||||
TEST(Unit, one_root)
|
||||
{
|
||||
EXPECT_EQ(Unit::Area.root(1), Unit::Area);
|
||||
}
|
||||
|
||||
TEST(Unit, TestPow3div2)
|
||||
{
|
||||
EXPECT_THROW([[maybe_unused]] auto res = Unit::Volume.pow(3.0 / 2.0), UnitsMismatchError);
|
||||
}
|
||||
|
||||
TEST(Unit, overflow)
|
||||
{
|
||||
constexpr UnitExponents arr {99, 0, 0, 0, 0, 0, 0, 0};
|
||||
EXPECT_THROW([[maybe_unused]] auto res = Unit {arr}, OverflowError);
|
||||
}
|
||||
|
||||
TEST(Unit, underflow)
|
||||
{
|
||||
constexpr UnitExponents arr {-99, 0, 0, 0, 0, 0, 0, 0};
|
||||
EXPECT_THROW([[maybe_unused]] auto res = Unit {arr}, UnderflowError);
|
||||
}
|
||||
|
||||
TEST(Unit, representation_simple)
|
||||
{
|
||||
const std::string expect {"Unit: mm (1,0,0,0,0,0,0,0) [Length]"};
|
||||
const auto actual = Unit::Length.representation();
|
||||
EXPECT_EQ(actual, expect);
|
||||
}
|
||||
|
||||
TEST(Unit, representation_complex)
|
||||
{
|
||||
const std::string expect {"Unit: mm^2*kg/(s^2*A) (2,1,-2,-1,0,0,0,0) [MagneticFlux]"};
|
||||
const auto actual = Unit::MagneticFlux.representation();
|
||||
EXPECT_EQ(actual, expect);
|
||||
}
|
||||
|
||||
TEST(Unit, representation_no_name)
|
||||
{
|
||||
constexpr Unit unit {{1, 1}};
|
||||
const std::string expect {"Unit: mm*kg (1,1,0,0,0,0,0,0)"};
|
||||
const auto actual = unit.representation();
|
||||
EXPECT_EQ(actual, expect);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user