Base: UnitsSchema: use basic imperial conversion constants

Use well defined basic constants for conversion of imperial units.
This makes code hopefully easily readable and verificable.
This commit is contained in:
Ladislav Michl
2025-09-03 07:54:47 +02:00
parent 1cd47c2dd4
commit 88f76f3605
6 changed files with 109 additions and 66 deletions

View File

@@ -152,6 +152,7 @@ SET(FreeCADBase_UNITAPI_SRCS
UnitsApi.cpp UnitsApi.cpp
UnitsApiPy.cpp UnitsApiPy.cpp
UnitsApi.h UnitsApi.h
UnitsConvData.h
UnitsSchema.h UnitsSchema.h
UnitsSchema.cpp UnitsSchema.cpp
UnitsSchemas.cpp UnitsSchemas.cpp

View File

@@ -36,6 +36,7 @@
#include "Quantity.h" #include "Quantity.h"
#include "Tools.h" #include "Tools.h"
#include "UnitsApi.h" #include "UnitsApi.h"
#include "UnitsConvData.h"
#include "UnitsSchema.h" #include "UnitsSchema.h"
/** \defgroup Units Units system /** \defgroup Units Units system
@@ -324,6 +325,8 @@ void Quantity::setInvalid()
// === Predefined types ===================================================== // === Predefined types =====================================================
// clang-format off // clang-format off
using namespace Base::UnitsConvData;
const Quantity Quantity::NanoMetre ( 1.0e-6 , Unit::Length ); const Quantity Quantity::NanoMetre ( 1.0e-6 , Unit::Length );
const Quantity Quantity::MicroMetre ( 1.0e-3 , Unit::Length ); const Quantity Quantity::MicroMetre ( 1.0e-3 , Unit::Length );
const Quantity Quantity::MilliMetre ( 1.0 , Unit::Length ); const Quantity Quantity::MilliMetre ( 1.0 , Unit::Length );
@@ -365,22 +368,23 @@ const Quantity Quantity::Mole ( 1.0 , Unit::
const Quantity Quantity::Candela ( 1.0 , Unit::LuminousIntensity ); const Quantity Quantity::Candela ( 1.0 , Unit::LuminousIntensity );
const Quantity Quantity::Inch ( 25.4 , Unit::Length ); const Quantity Quantity::Inch ( in , Unit::Length );
const Quantity Quantity::Foot ( 304.8 , Unit::Length ); const Quantity Quantity::Foot ( ft , Unit::Length );
const Quantity Quantity::Thou ( 0.0254 , Unit::Length ); const Quantity Quantity::Thou ( in / 1000 , Unit::Length );
const Quantity Quantity::Yard ( 914.4 , Unit::Length ); const Quantity Quantity::Yard ( yd , Unit::Length );
const Quantity Quantity::Mile ( 1609344.0 , Unit::Length ); const Quantity Quantity::Mile ( mi , Unit::Length );
const Quantity Quantity::MilePerHour ( 447.04 , Unit::Velocity ); const Quantity Quantity::MilePerHour ( mi / 3600 , Unit::Velocity );
const Quantity Quantity::SquareFoot ( 92903.04 , Unit::Area );
const Quantity Quantity::CubicFoot ( 28316846.592 , Unit::Volume );
const Quantity Quantity::Pound ( 0.45359237 , Unit::Mass ); const Quantity Quantity::SquareFoot ( ft * ft , Unit::Area );
const Quantity Quantity::Ounce ( 0.0283495231 , Unit::Mass ); const Quantity Quantity::CubicFoot ( ft * ft * ft , Unit::Volume );
const Quantity Quantity::Stone ( 6.35029318 , Unit::Mass );
const Quantity Quantity::Hundredweights ( 50.80234544 , Unit::Mass );
const Quantity Quantity::PoundForce ( 4448.22 , Unit::Force ); // lbf are ~= 4.44822 Newton const Quantity Quantity::Pound ( lb , Unit::Mass );
const Quantity Quantity::Ounce ( lb / 16 , Unit::Mass );
const Quantity Quantity::Stone ( lb * 14 , Unit::Mass );
const Quantity Quantity::Hundredweights ( lb * 112 , Unit::Mass );
const Quantity Quantity::PoundForce ( 1000 * lbf , Unit::Force );
const Quantity Quantity::Newton ( 1000.0 , Unit::Force ); // Newton (kg*m/s^2) const Quantity Quantity::Newton ( 1000.0 , Unit::Force ); // Newton (kg*m/s^2)
const Quantity Quantity::MilliNewton ( 1.0 , Unit::Force ); const Quantity Quantity::MilliNewton ( 1.0 , Unit::Force );
@@ -401,12 +405,12 @@ const Quantity Quantity::MilliBar ( 0.1 , Unit::
const Quantity Quantity::Bar ( 100.0 , Unit::Pressure ); // 1 bar = 100 kPa const Quantity Quantity::Bar ( 100.0 , Unit::Pressure ); // 1 bar = 100 kPa
const Quantity Quantity::Torr ( 101.325 / 760.0 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2) const Quantity Quantity::Torr ( 101.325 / 760.0 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
const Quantity Quantity::mTorr ( 0.101325 / 760.0 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2) const Quantity Quantity::mTorr ( 101.325 / 760.0 / 1e3 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
const Quantity Quantity::yTorr ( 0.000101325 / 760.0 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2) const Quantity Quantity::yTorr ( 101.325 / 760.0 / 1e6 , Unit::Pressure ); // Torr is a defined fraction of Pascal (kg/m/s^2 or N/m^2)
const Quantity Quantity::PSI ( 6.894744825494 , Unit::Pressure ); // pounds/in^2 const Quantity Quantity::PSI ( psi , Unit::Pressure );
const Quantity Quantity::KSI ( 6894.744825494 , Unit::Pressure ); // 1000 x pounds/in^2 const Quantity Quantity::KSI ( psi * 1000 , Unit::Pressure );
const Quantity Quantity::MPSI ( 6894744.825494 , Unit::Pressure ); // 1000 ksi const Quantity Quantity::MPSI ( psi * 1000000 , Unit::Pressure );
const Quantity Quantity::Watt ( 1e+6 , Unit::Power ); // Watt (kg*m^2/s^3) 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::MilliWatt ( 1e+3 , Unit::Power );
@@ -458,8 +462,8 @@ const Quantity Quantity::Calorie ( 4.1868e+6 , Unit::
const Quantity Quantity::KiloCalorie ( 4.1868e+9 , Unit::Work ); const Quantity Quantity::KiloCalorie ( 4.1868e+9 , Unit::Work );
const Quantity Quantity::NewtonMeter ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2) const Quantity Quantity::NewtonMeter ( 1e+6 , Unit::Moment ); // Joule (kg*m^2/s^2)
const Quantity Quantity::KMH ( 277.778 , Unit::Velocity ); // km/h const Quantity Quantity::KMH ( 1e+6 / 3600 , Unit::Velocity ); // km/h
const Quantity Quantity::MPH ( 447.04 , Unit::Velocity ); // Mile/h const Quantity Quantity::MPH ( mi / 3600 , Unit::Velocity ); // Mile/h
const Quantity Quantity::AngMinute ( 1.0 / 60.0 , Unit::Angle ); // angular minute 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::AngSecond ( 1.0 / 3600.0 , Unit::Angle ); // angular second

View File

@@ -195,7 +195,6 @@ public:
/// sets the quantity invalid /// sets the quantity invalid
void setInvalid(); void setInvalid();
/** Predefined Unit types. */ /** Predefined Unit types. */
//@{ //@{
static const Quantity NanoMetre; static const Quantity NanoMetre;
@@ -243,14 +242,15 @@ public:
static const Quantity Foot; static const Quantity Foot;
static const Quantity Thou; static const Quantity Thou;
static const Quantity Yard; static const Quantity Yard;
static const Quantity Mile;
static const Quantity MilePerHour;
static const Quantity Pound; static const Quantity Pound;
static const Quantity Ounce; static const Quantity Ounce;
static const Quantity Stone; static const Quantity Stone;
static const Quantity Hundredweights; static const Quantity Hundredweights;
static const Quantity Mile;
static const Quantity MilePerHour;
static const Quantity SquareFoot; static const Quantity SquareFoot;
static const Quantity CubicFoot; static const Quantity CubicFoot;
@@ -308,8 +308,6 @@ public:
static const Quantity Weber; static const Quantity Weber;
// static const Quantity Oersted;
static const Quantity Farad; static const Quantity Farad;
static const Quantity MilliFarad; static const Quantity MilliFarad;
static const Quantity MicroFarad; static const Quantity MicroFarad;
@@ -344,7 +342,6 @@ public:
static const Quantity AngSecond; static const Quantity AngSecond;
//@} //@}
private: private:
double myValue; double myValue;
Unit myUnit; Unit myUnit;

38
src/Base/UnitsConvData.h Normal file
View File

@@ -0,0 +1,38 @@
/************************************************************************
* *
* 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 *
* *
************************************************************************/
#ifndef BASE_UNITSCONVDATA_H
#define BASE_UNITSCONVDATA_H
namespace Base::UnitsConvData
{
constexpr auto in {25.4};
constexpr auto ft {12 * in};
constexpr auto yd {3 * ft};
constexpr auto mi {1760 * yd};
constexpr auto lb {0.45359237};
constexpr auto lbf {9.80665 * lb};
constexpr auto psi {lbf / (in * in) * 1000};
} // namespace Base::UnitsConvData
#endif

View File

@@ -30,6 +30,7 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "fmt/ranges.h" #include "fmt/ranges.h"
#include "UnitsConvData.h"
#include "UnitsSchemasSpecs.h" #include "UnitsSchemasSpecs.h"
/** /**
@@ -42,6 +43,8 @@ namespace Base::UnitsSchemasData
constexpr std::size_t defDecimals {2}; constexpr std::size_t defDecimals {2};
constexpr std::size_t defDenominator {8}; constexpr std::size_t defDenominator {8};
using namespace Base::UnitsConvData;
// NOLINTBEGIN // NOLINTBEGIN
// clang-format off // clang-format off
inline const UnitsSchemaSpec s0 inline const UnitsSchemaSpec s0
@@ -69,15 +72,15 @@ inline const UnitsSchemaSpec s1
inline const UnitsSchemaSpec s2 inline const UnitsSchemaSpec s2
{ 3, "ImperialDecimal", "in", false, false, QT_TRANSLATE_NOOP("UnitsApi", "Imperial decimal (in, lb)"), false, { 3, "ImperialDecimal", "in", false, false, QT_TRANSLATE_NOOP("UnitsApi", "Imperial decimal (in, lb)"), false,
{ {
{ "Length", {{ 0 , "in" , 25.4 }}}, { "Length", {{ 0 , "in" , in }}},
{ "Angle", {{ 0 , "°" , 1.0 }}}, { "Angle", {{ 0 , "°" , 1.0 }}},
{ "Area", {{ 0 , "in^2" , 645.16 }}}, { "Area", {{ 0 , "in^2" , in * in }}},
{ "Volume", {{ 0 , "in^3" , 16387.064 }}}, { "Volume", {{ 0 , "in^3" , in * in * in }}},
{ "Mass", {{ 0 , "lb" , 0.45359237 }}}, { "Mass", {{ 0 , "lb" , lb }}},
{ "Pressure", {{ 0 , "psi" , 6.894744825494 }}}, { "Pressure", {{ 0 , "psi" , psi }}},
{ "Stiffness", {{ 0 , "lbf/in" , 4.448222 / 0.0254 }}}, { "Stiffness", {{ 0 , "lbf/in" , lbf / in * 1000 }}},
{ "Velocity", {{ 0 , "in/min" , 25.4 / 60 }}}, { "Velocity", {{ 0 , "in/min" , in / 60 }}},
{ "Acceleration", {{ 0 , "in/min^2", 25.4 / 3600 }}} { "Acceleration", {{ 0 , "in/min^2", in / 3600 }}}
} }
}; };
@@ -582,36 +585,36 @@ inline const UnitsSchemaSpec s7
{ 2, "Imperial", "in", false, false, QT_TRANSLATE_NOOP("UnitsApi", "US customary (in, lb)"), false, { 2, "Imperial", "in", false, false, QT_TRANSLATE_NOOP("UnitsApi", "US customary (in, lb)"), false,
{ {
{ "Length", { { "Length", {
{ 0.00000254 , "in" , 25.4 }, { 0.00000254 , "in" , in },
{ 2.54 , "thou" , 0.0254 }, { 2.54 , "thou" , in / 1000 },
{ 304.8 , "\"" , 25.4 }, { 304.8 , "\"" , in },
{ 914.4 , "'" , 304.8 }, { 914.4 , "'" , ft },
{ 1'609'344.0 , "yd" , 914.4 }, { 1'609'344.0 , "yd" , yd },
{ 1'609'344'000.0 , "mi" , 1'609'344.0 }, { 1'609'344'000.0 , "mi" , mi },
{ 0 , "in" , 25.4 }} { 0 , "in" , in }}
}, },
{ "Angle", { { "Angle", {
{ 0 , "°" , 1.0 }} { 0 , "°" , 1.0 }}
}, },
{ "Area", { { "Area", {
{ 0 , "in^2" , 645.16 }} { 0 , "in^2" , in * in }}
}, },
{ "Volume", { { "Volume", {
{ 0 , "in^3" , 16'387.064 }} { 0 , "in^3" , in * in * in }}
}, },
{ "Mass", { { "Mass", {
{ 0 , "lb" , 0.45359237 }} { 0 , "lb" , lb }}
}, },
{ "Pressure", { { "Pressure", {
{ 6'894.744 , "psi" , 6.894744825494 }, { 1000 * psi , "psi" , psi },
{ 6'894'744.825 , "ksi" , 6'894.744825494 }, { 1000000 * psi , "ksi" , 1000 * psi },
{ 0 , "psi" , 6.894744825494 }} { 0 , "psi" , psi }}
}, },
{ "Stiffness", { { "Stiffness", {
{ 0 , "lbf/in" , 4.448222 / 0.0254 }} { 0 , "lbf/in" , lbf / in * 1000 }}
}, },
{ "Velocity", { { "Velocity", {
{ 0 , "in/min" , 25.4 / 60 }} { 0 , "in/min" , in / 60 }}
} }
} }
}; };
@@ -621,22 +624,22 @@ inline const UnitsSchemaSpec s8
{ {
{ "Length" , {{ 0 , "toFractional" , 0 }}}, // <== ! { "Length" , {{ 0 , "toFractional" , 0 }}}, // <== !
{ "Angle" , {{ 0 , "°" , 1.0 }}}, { "Angle" , {{ 0 , "°" , 1.0 }}},
{ "Area" , {{ 0 , "sqft" , 92'903.04 }}}, { "Area" , {{ 0 , "sqft" , ft * ft }}},
{ "Volume" , {{ 0 , "cft" , 28'316'846.592 }}}, { "Volume" , {{ 0 , "cft" , ft * ft * ft }}},
{ "Velocity" , {{ 0 , "in/min" , 25.4 / 60 }}} { "Velocity" , {{ 0 , "in/min" , in / 60 }}}
} }
}; };
inline const UnitsSchemaSpec s9 inline const UnitsSchemaSpec s9
{ 7, "ImperialCivil", "ft", false, true, QT_TRANSLATE_NOOP("UnitsApi", "Imperial for Civil Eng (ft, lb, mph)"), false, { 7, "ImperialCivil", "ft", false, true, QT_TRANSLATE_NOOP("UnitsApi", "Imperial for Civil Eng (ft, lb, mph)"), false,
{ {
{ "Length" , {{ 0 , "ft" , 12 * 25.4 }}}, { "Length" , {{ 0 , "ft" , ft }}},
{ "Area" , {{ 0 , "ft^2" , 92'903.04 }}}, { "Area" , {{ 0 , "ft^2" , ft * ft }}},
{ "Volume" , {{ 0 , "ft^3" , 28'316'846.592 }}}, { "Volume" , {{ 0 , "ft^3" , ft * ft * ft }}},
{ "Mass" , {{ 0 , "lb" , 0.45359237 }}}, { "Mass" , {{ 0 , "lb" , lb }}},
{ "Pressure" , {{ 0 , "psi" , 6.894744825494 }}}, { "Pressure" , {{ 0 , "psi" , psi }}},
{ "Stiffness", {{ 0 , "lbf/in", 4.448222 / 0.0254 }}}, { "Stiffness", {{ 0 , "lbf/in", lbf / in * 1000 }}},
{ "Velocity" , {{ 0 , "mph" , 447.04 }}}, { "Velocity" , {{ 0 , "mph" , mi / 3600 }}},
{ "Angle" , {{ 0 , "toDMS" , 0 }}} // <== ! { "Angle" , {{ 0 , "toDMS" , 0 }}} // <== !
} }
}; };

View File

@@ -198,25 +198,25 @@ protected:
TEST_F(BaseQuantityLoc, psi_parse_spaced) TEST_F(BaseQuantityLoc, psi_parse_spaced)
{ {
const auto qParsed = Quantity::parse("1 psi"); const auto qParsed = Quantity::parse("1 psi");
EXPECT_EQ(qParsed.getValue(), 6.8947448254939996); EXPECT_EQ(qParsed.getValue(), 6.8947572931683609);
} }
TEST_F(BaseQuantityLoc, psi_parse_no_space) TEST_F(BaseQuantityLoc, psi_parse_no_space)
{ {
const auto qParsed = Quantity::parse("1psi"); const auto qParsed = Quantity::parse("1psi");
EXPECT_EQ(qParsed.getValue(), 6.8947448254939996); EXPECT_EQ(qParsed.getValue(), 6.8947572931683609);
} }
TEST_F(BaseQuantityLoc, psi_parse_user_str) TEST_F(BaseQuantityLoc, psi_parse_user_str)
{ {
const auto qParsed = Quantity::parse("1 psi"); const auto qParsed = Quantity::parse("1 psi");
EXPECT_EQ(qParsed.getUserString(), "6894.74 Pa"); EXPECT_EQ(qParsed.getUserString(), "6894.76 Pa");
} }
TEST_F(BaseQuantityLoc, psi_parse_safe_user_str) TEST_F(BaseQuantityLoc, psi_parse_safe_user_str)
{ {
const auto qParsed = Quantity::parse("1 psi"); const auto qParsed = Quantity::parse("1 psi");
EXPECT_EQ(qParsed.getSafeUserString(), "6894.74 Pa"); EXPECT_EQ(qParsed.getSafeUserString(), "6894.76 Pa");
} }
TEST_F(BaseQuantityLoc, psi_parse_unit_type) TEST_F(BaseQuantityLoc, psi_parse_unit_type)
@@ -228,7 +228,7 @@ TEST_F(BaseQuantityLoc, psi_parse_unit_type)
TEST_F(BaseQuantityLoc, psi_to_Pa) TEST_F(BaseQuantityLoc, psi_to_Pa)
{ {
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::Pascal); const auto result = Quantity::parse("1 psi").getValueAs(Quantity::Pascal);
const auto expect = 6894.7448254939991; const auto expect = 6894.7572931683608;
EXPECT_EQ(result, expect); EXPECT_EQ(result, expect);
} }
@@ -236,7 +236,7 @@ TEST_F(BaseQuantityLoc, psi_to_Pa)
TEST_F(BaseQuantityLoc, psi_to_KPa) TEST_F(BaseQuantityLoc, psi_to_KPa)
{ {
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::KiloPascal); const auto result = Quantity::parse("1 psi").getValueAs(Quantity::KiloPascal);
const auto expect = 6.8947448254939996; const auto expect = 6.8947572931683609;
EXPECT_EQ(result, expect); EXPECT_EQ(result, expect);
} }
@@ -244,7 +244,7 @@ TEST_F(BaseQuantityLoc, psi_to_KPa)
TEST_F(BaseQuantityLoc, psi_to_MPa) TEST_F(BaseQuantityLoc, psi_to_MPa)
{ {
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::MegaPascal); const auto result = Quantity::parse("1 psi").getValueAs(Quantity::MegaPascal);
const auto expect = 0.0068947448254939999; const auto expect = 0.0068947572931683607;
EXPECT_EQ(result, expect); EXPECT_EQ(result, expect);
} }