Merge pull request #23384 from 3x380V/units

Base: Units update
This commit is contained in:
Chris Hennes
2025-09-07 20:22:54 -05:00
committed by GitHub
21 changed files with 309 additions and 293 deletions

View File

@@ -2782,8 +2782,7 @@ void Application::initApplication()
("User parameter:BaseApp/Preferences/Units");
Base::UnitsApi::setSchema(hGrp->GetInt("UserSchema", Base::UnitsApi::getDefSchemaNum()));
Base::UnitsApi::setDecimals(hGrp->GetInt("Decimals", Base::UnitsApi::getDecimals()));
Base::QuantityFormat::setDefaultDenominator(
hGrp->GetInt("FracInch", Base::QuantityFormat::getDefaultDenominator()));
Base::UnitsApi::setDenominator(hGrp->GetInt("FracInch", Base::UnitsApi::getDenominator()));
#if defined (_DEBUG)
Base::Console().log("Application is built with debug information\n");

View File

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

View File

@@ -26,6 +26,7 @@
#include <cmath>
#include <limits>
#include <numbers>
#include <sstream>
#include <string>
#endif
@@ -35,6 +36,7 @@
#include "Quantity.h"
#include "Tools.h"
#include "UnitsApi.h"
#include "UnitsConvData.h"
#include "UnitsSchema.h"
/** \defgroup Units Units system
@@ -56,25 +58,30 @@ using Base::Quantity;
using Base::QuantityFormat;
using Base::UnitsSchema;
// ====== Static attributes =========================
// NOLINTNEXTLINE
int QuantityFormat::defaultDenominator = 8; // for 1/8"
QuantityFormat::QuantityFormat()
: option(OmitGroupSeparator | RejectGroupSeparator)
, format(Fixed)
, precision(static_cast<int>(UnitsApi::getDecimals()))
, denominator(defaultDenominator)
, _precision(-1)
, _denominator(-1)
{}
QuantityFormat::QuantityFormat(QuantityFormat::NumberFormat format, int decimals)
: option(OmitGroupSeparator | RejectGroupSeparator)
, format(format)
, precision(decimals < 0 ? UnitsApi::getDecimals() : decimals)
, denominator(defaultDenominator)
, _precision(decimals)
, _denominator(-1)
{}
int QuantityFormat::getPrecision() const
{
return _precision < 0 ? UnitsApi::getDecimals() : _precision;
}
int QuantityFormat::getDenominator() const
{
return _denominator < 0 ? UnitsApi::getDenominator() : _denominator;
}
// ----------------------------------------------------------------------------
Quantity::Quantity()
@@ -87,22 +94,21 @@ Quantity::Quantity(double value, const Unit& unit)
{}
Quantity::Quantity(double value, const std::string& unit)
: myValue {0.0}
{
if (unit.empty()) {
this->myValue = value;
this->myUnit = Unit();
myValue = value;
myUnit = Unit();
return;
}
try {
auto tmpQty = parse(unit);
this->myUnit = tmpQty.getUnit();
this->myValue = value * tmpQty.getValue();
myValue = value * tmpQty.getValue();
myUnit = tmpQty.getUnit();
}
catch (const Base::ParserError&) {
this->myValue = 0.0;
this->myUnit = Unit();
myValue = 0.0;
myUnit = Unit();
}
}
@@ -113,7 +119,7 @@ double Quantity::getValueAs(const Quantity& other) const
bool Quantity::operator==(const Quantity& that) const
{
return (this->myValue == that.myValue) && (this->myUnit == that.myUnit);
return (myValue == that.myValue) && (myUnit == that.myUnit);
}
bool Quantity::operator!=(const Quantity& that) const
@@ -123,62 +129,62 @@ bool Quantity::operator!=(const Quantity& that) const
bool Quantity::operator<(const Quantity& that) const
{
if (this->myUnit != that.myUnit) {
if (myUnit != that.myUnit) {
throw Base::UnitsMismatchError(
"Quantity::operator <(): quantities need to have same unit to compare");
}
return (this->myValue < that.myValue);
return (myValue < that.myValue);
}
bool Quantity::operator>(const Quantity& that) const
{
if (this->myUnit != that.myUnit) {
if (myUnit != that.myUnit) {
throw Base::UnitsMismatchError(
"Quantity::operator >(): quantities need to have same unit to compare");
}
return (this->myValue > that.myValue);
return (myValue > that.myValue);
}
bool Quantity::operator<=(const Quantity& that) const
{
if (this->myUnit != that.myUnit) {
if (myUnit != that.myUnit) {
throw Base::UnitsMismatchError(
"Quantity::operator <=(): quantities need to have same unit to compare");
}
return (this->myValue <= that.myValue);
return (myValue <= that.myValue);
}
bool Quantity::operator>=(const Quantity& that) const
{
if (this->myUnit != that.myUnit) {
if (myUnit != that.myUnit) {
throw Base::UnitsMismatchError(
"Quantity::operator >=(): quantities need to have same unit to compare");
}
return (this->myValue >= that.myValue);
return (myValue >= that.myValue);
}
Quantity Quantity::operator*(const Quantity& other) const
{
return Quantity(this->myValue * other.myValue, this->myUnit * other.myUnit);
return Quantity(myValue * other.myValue, myUnit * other.myUnit);
}
Quantity Quantity::operator*(double factor) const
{
return Quantity(this->myValue * factor, this->myUnit);
return Quantity(myValue * factor, myUnit);
}
Quantity Quantity::operator/(const Quantity& other) const
{
return Quantity(this->myValue / other.myValue, this->myUnit / other.myUnit);
return Quantity(myValue / other.myValue, myUnit / other.myUnit);
}
Quantity Quantity::operator/(double factor) const
{
return Quantity(this->myValue / factor, this->myUnit);
return Quantity(myValue / factor, myUnit);
}
Quantity Quantity::pow(const Quantity& other) const
@@ -187,27 +193,27 @@ Quantity Quantity::pow(const Quantity& other) const
throw Base::UnitsMismatchError("Quantity::pow(): exponent must not have a unit");
}
return Quantity(std::pow(this->myValue, other.myValue),
this->myUnit.pow(static_cast<signed char>(other.myValue)));
return Quantity(std::pow(myValue, other.myValue),
myUnit.pow(static_cast<signed char>(other.myValue)));
}
Quantity Quantity::pow(double exp) const
{
return Quantity(std::pow(this->myValue, exp), this->myUnit.pow(exp));
return Quantity(std::pow(myValue, exp), myUnit.pow(exp));
}
Quantity Quantity::operator+(const Quantity& other) const
{
if (this->myUnit != other.myUnit) {
if (myUnit != other.myUnit) {
throw Base::UnitsMismatchError("Quantity::operator +(): Unit mismatch in plus operation");
}
return Quantity(this->myValue + other.myValue, this->myUnit);
return Quantity(myValue + other.myValue, myUnit);
}
Quantity& Quantity::operator+=(const Quantity& other)
{
if (this->myUnit != other.myUnit) {
if (myUnit != other.myUnit) {
throw Base::UnitsMismatchError("Quantity::operator +=(): Unit mismatch in plus operation");
}
@@ -218,16 +224,16 @@ Quantity& Quantity::operator+=(const Quantity& other)
Quantity Quantity::operator-(const Quantity& other) const
{
if (this->myUnit != other.myUnit) {
if (myUnit != other.myUnit) {
throw Base::UnitsMismatchError("Quantity::operator -(): Unit mismatch in minus operation");
}
return Quantity(this->myValue - other.myValue, this->myUnit);
return Quantity(myValue - other.myValue, myUnit);
}
Quantity& Quantity::operator-=(const Quantity& other)
{
if (this->myUnit != other.myUnit) {
if (myUnit != other.myUnit) {
throw Base::UnitsMismatchError("Quantity::operator -=(): Unit mismatch in minus operation");
}
@@ -238,7 +244,31 @@ Quantity& Quantity::operator-=(const Quantity& other)
Quantity Quantity::operator-() const
{
return Quantity(-(this->myValue), this->myUnit);
return Quantity(-myValue, myUnit);
}
std::string Quantity::toString(const QuantityFormat& format) const
{
return fmt::format("'{} {}'", toNumber(format), myUnit.getString());
}
std::string Quantity::toNumber(const QuantityFormat& format) const
{
std::stringstream ss;
switch (format.format) {
case QuantityFormat::Fixed:
ss << std::fixed;
break;
case QuantityFormat::Scientific:
ss << std::scientific;
break;
default:
break;
}
ss << std::setprecision(format.getPrecision()) << myValue;
return ss.str();
}
std::string Quantity::getUserString() const
@@ -295,6 +325,8 @@ void Quantity::setInvalid()
// === Predefined types =====================================================
// clang-format off
using namespace Base::UnitsConvData;
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 );
@@ -336,22 +368,23 @@ const Quantity Quantity::Mole ( 1.0 , Unit::
const Quantity Quantity::Candela ( 1.0 , Unit::LuminousIntensity );
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 ( in , Unit::Length );
const Quantity Quantity::Foot ( ft , Unit::Length );
const Quantity Quantity::Thou ( in / 1000 , Unit::Length );
const Quantity Quantity::Yard ( yd , Unit::Length );
const Quantity Quantity::Mile ( mi , Unit::Length );
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 ( mi / 3600 , Unit::Velocity );
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::SquareFoot ( ft * ft , Unit::Area );
const Quantity Quantity::CubicFoot ( ft * ft * ft , Unit::Volume );
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::MilliNewton ( 1.0 , Unit::Force );
@@ -363,21 +396,21 @@ const Quantity Quantity::MilliNewtonPerMeter ( 1e-3 , Unit::
const Quantity Quantity::KiloNewtonPerMeter ( 1e3 , Unit::Stiffness );
const Quantity Quantity::MegaNewtonPerMeter ( 1e6 , Unit::Stiffness );
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::Pressure ); // Pascal (kg/m/s^2 or N/m^2)
const Quantity Quantity::KiloPascal ( 1.00 , Unit::Pressure );
const Quantity Quantity::MegaPascal ( 1000.0 , Unit::Pressure );
const Quantity Quantity::GigaPascal ( 1e+6 , Unit::Pressure );
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::Pressure );
const Quantity Quantity::Bar ( 100.0 , Unit::Pressure ); // 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::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 ( 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::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 ( psi , Unit::Pressure );
const Quantity Quantity::KSI ( psi * 1000 , Unit::Pressure );
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::MilliWatt ( 1e+3 , Unit::Power );
@@ -429,8 +462,8 @@ const Quantity Quantity::Calorie ( 4.1868e+6 , Unit::
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::KMH ( 277.778 , Unit::Velocity ); // km/h
const Quantity Quantity::MPH ( 447.04 , Unit::Velocity ); // Mile/h
const Quantity Quantity::KMH ( 1e+6 / 3600 , Unit::Velocity ); // km/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::AngSecond ( 1.0 / 3600.0 , Unit::Angle ); // angular second

View File

@@ -49,33 +49,19 @@ struct BaseExport QuantityFormat
using NumberOptions = int;
NumberOptions option;
NumberFormat format;
int precision;
int denominator;
// Default denominator of minimum fractional inch. Only used in certain
// schemas.
// NOLINTNEXTLINE
static int defaultDenominator; // i.e 8 for 1/8"
static inline int getDefaultDenominator()
int getPrecision() const;
inline void setPrecision(int precision)
{
return defaultDenominator;
_precision = precision;
}
static inline void setDefaultDenominator(int denom)
int getDenominator() const;
inline void setDenominator(int denominator)
{
defaultDenominator = denom;
_denominator = denominator;
}
inline int getDenominator() const
{
return denominator;
}
inline void setDenominator(int denom)
{
denominator = denom;
}
QuantityFormat();
explicit QuantityFormat(NumberFormat format, int decimals = -1);
inline char toFormat() const
@@ -108,6 +94,9 @@ struct BaseExport QuantityFormat
return Default;
}
}
private:
int _precision, _denominator;
};
/**
@@ -157,6 +146,12 @@ public:
myFormat = fmt;
}
std::string
toString(const QuantityFormat& format = QuantityFormat(QuantityFormat::Default)) const;
std::string
toNumber(const QuantityFormat& format = QuantityFormat(QuantityFormat::Default)) const;
std::string getUserString() const;
/// transfer to user preferred unit/potence
std::string getUserString(double& factor, std::string& unitString) const;
@@ -200,7 +195,6 @@ public:
/// sets the quantity invalid
void setInvalid();
/** Predefined Unit types. */
//@{
static const Quantity NanoMetre;
@@ -248,14 +242,15 @@ public:
static const Quantity Foot;
static const Quantity Thou;
static const Quantity Yard;
static const Quantity Mile;
static const Quantity MilePerHour;
static const Quantity Pound;
static const Quantity Ounce;
static const Quantity Stone;
static const Quantity Hundredweights;
static const Quantity Mile;
static const Quantity MilePerHour;
static const Quantity SquareFoot;
static const Quantity CubicFoot;
@@ -313,8 +308,6 @@ public:
static const Quantity Weber;
// static const Quantity Oersted;
static const Quantity Farad;
static const Quantity MilliFarad;
static const Quantity MicroFarad;
@@ -349,7 +342,6 @@ public:
static const Quantity AngSecond;
//@}
private:
double myValue;
Unit myUnit;

View File

@@ -57,7 +57,7 @@ std::string QuantityPy::representation() const
PyObject* QuantityPy::toStr(PyObject* args) const
{
int prec = getQuantityPtr()->getFormat().precision;
int prec = getQuantityPtr()->getFormat().getPrecision();
if (!PyArg_ParseTuple(args, "|i", &prec)) {
return nullptr;
}
@@ -669,9 +669,9 @@ Py::Dict QuantityPy::getFormat() const
QuantityFormat fmt = getQuantityPtr()->getFormat();
Py::Dict dict;
dict.setItem("Precision", Py::Long(fmt.precision));
dict.setItem("Precision", Py::Long(fmt.getPrecision()));
dict.setItem("NumberFormat", Py::Char(fmt.toFormat()));
dict.setItem("Denominator", Py::Long(fmt.denominator));
dict.setItem("Denominator", Py::Long(fmt.getDenominator()));
return dict;
}
@@ -681,7 +681,7 @@ void QuantityPy::setFormat(Py::Dict arg)
if (arg.hasKey("Precision")) {
Py::Long prec(arg.getItem("Precision"));
fmt.precision = static_cast<int>(prec);
fmt.setPrecision(static_cast<int>(prec));
}
if (arg.hasKey("NumberFormat")) {
@@ -719,7 +719,7 @@ void QuantityPy::setFormat(Py::Dict arg)
if (fracInch & (fracInch - 1)) {
throw Py::ValueError("Denominator must be a power of two");
}
fmt.denominator = fracInch;
fmt.setDenominator(fracInch);
}
getQuantityPtr()->setFormat(fmt);

View File

@@ -23,11 +23,9 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <iomanip>
#include <sstream>
#endif
#include <CXX/WrapPython.h>
#include <fmt/format.h>
#include "Exception.h"
#include "UnitsApi.h"
@@ -39,11 +37,6 @@ using Base::UnitsApi;
using Base::UnitsSchema;
using Base::UnitsSchemas;
void UnitsApi::init()
{
schemas = std::make_unique<UnitsSchemas>(UnitsSchemasData::unitSchemasDataPack);
}
std::vector<std::string> UnitsApi::getDescriptions()
{
return schemas->descriptions();
@@ -74,9 +67,24 @@ std::string UnitsApi::getBasicLengthUnit()
return schemas->currentSchema()->getBasicLengthUnit();
}
std::size_t UnitsApi::getFractDenominator()
void UnitsApi::setDecimals(const int prec)
{
return schemas->defFractDenominator();
decimals = prec;
}
int UnitsApi::getDecimals()
{
return decimals < 0 ? schemas->getDecimals() : decimals;
}
void UnitsApi::setDenominator(int frac)
{
denominator = frac;
}
int UnitsApi::getDenominator()
{
return denominator < 0 ? schemas->defFractDenominator() : denominator;
}
std::unique_ptr<UnitsSchema> UnitsApi::createSchema(const std::size_t num)
@@ -94,35 +102,6 @@ void UnitsApi::setSchema(const size_t num)
schemas->select(num);
}
std::string UnitsApi::toString(const Quantity& quantity, const QuantityFormat& format)
{
return fmt::format("'{} {}'", toNumber(quantity, format), quantity.getUnit().getString());
}
std::string UnitsApi::toNumber(const Quantity& quantity, const QuantityFormat& format)
{
return toNumber(quantity.getValue(), format);
}
std::string UnitsApi::toNumber(const double value, const QuantityFormat& format)
{
std::stringstream ss;
switch (format.format) {
case QuantityFormat::Fixed:
ss << std::fixed;
break;
case QuantityFormat::Scientific:
ss << std::scientific;
break;
default:
break;
}
ss << std::setprecision(format.precision) << value;
return ss.str();
}
double UnitsApi::toDouble(PyObject* args, const Base::Unit& u)
{
if (PyUnicode_Check(args)) {
@@ -157,18 +136,3 @@ std::string UnitsApi::schemaTranslate(const Quantity& quant)
std::string dummy2;
return schemas->currentSchema()->translate(quant, dummy1, dummy2);
}
void UnitsApi::setDecimals(const std::size_t prec)
{
decimals = prec;
}
size_t UnitsApi::getDecimals()
{
return decimals;
}
size_t UnitsApi::getDefDecimals()
{
return schemas->getDecimals();
}

View File

@@ -41,7 +41,6 @@ namespace Base
class BaseExport UnitsApi
{
public:
static void init();
static std::unique_ptr<UnitsSchema> createSchema(std::size_t num);
static void setSchema(const std::string& name);
static void setSchema(std::size_t num);
@@ -51,32 +50,13 @@ public:
static std::string schemaTranslate(const Quantity& quant);
/**
* toString & toNumber:
* Quantity to string. Optionally apply format
* The string is a number in C locale (i.e. the decimal separator is always a dot)
* Scientific notation (if needed).
*/
/** INCLUDES unit */
static std::string
toString(const Quantity& quantity,
const QuantityFormat& format = QuantityFormat(QuantityFormat::Default));
/** Does NOT include unit */
static std::string
toNumber(const Quantity& quantity,
const QuantityFormat& format = QuantityFormat(QuantityFormat::Default));
/** Does NOT include unit */
static std::string
toNumber(double value, const QuantityFormat& format = QuantityFormat(QuantityFormat::Default));
static double toDouble(PyObject* args, const Base::Unit& u = Base::Unit());
static void setDecimals(std::size_t);
static std::size_t getDecimals();
static std::size_t getDefDecimals();
static void setDecimals(int);
static int getDecimals();
static void setDenominator(int);
static int getDenominator();
static std::vector<std::string> getDescriptions();
static std::vector<std::string> getNames();
@@ -86,7 +66,6 @@ public:
static bool isMultiUnitAngle();
static bool isMultiUnitLength();
static std::string getBasicLengthUnit();
static std::size_t getFractDenominator();
static std::size_t getDefSchemaNum()
{
@@ -98,8 +77,8 @@ public:
protected:
static inline auto schemas =
std::make_unique<UnitsSchemas>(UnitsSchemasData::unitSchemasDataPack);
static inline std::size_t decimals {2};
static inline std::size_t denominator {2};
static inline int decimals {-1};
static inline int denominator {-1};
// the python API wrapper methods
static PyObject* sParseQuantity(PyObject* self, PyObject* args);

View File

@@ -208,14 +208,13 @@ PyObject* UnitsApi::sToNumber(PyObject* /*self*/, PyObject* args)
}
bool ok {};
QuantityFormat qf;
qf.format = QuantityFormat::toFormat(format[0], &ok);
qf.precision = decimals;
QuantityFormat qf {QuantityFormat::toFormat(format[0], &ok), decimals};
if (!ok) {
PyErr_SetString(PyExc_ValueError, "Invalid format string");
return nullptr;
}
return Py::new_reference_to(Py::String(toNumber(value, qf)));
const Quantity quantity {value};
return Py::new_reference_to(Py::String(quantity.toNumber(qf)));
}

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

@@ -79,7 +79,13 @@ UnitsSchema::translate(const Quantity& quant, double& factor, std::string& unitS
}
if (unitSpec->factor == 0) {
return UnitsSchemasData::runSpecial(unitSpec->unitString, value, factor, unitString);
const QuantityFormat& format = quant.getFormat();
return UnitsSchemasData::runSpecial(unitSpec->unitString,
value,
format.getPrecision(),
format.getDenominator(),
factor,
unitString);
}
factor = unitSpec->factor;
@@ -98,7 +104,8 @@ UnitsSchema::toLocale(const Quantity& quant, const double factor, const std::str
}
auto valueString =
Lc.toString(quant.getValue() / factor, format.toFormat(), format.precision).toStdString();
Lc.toString(quant.getValue() / factor, format.toFormat(), format.getPrecision())
.toStdString();
auto notUnit = [](auto s) {
return s.empty() || s == "°" || s == "" || s == "" || s == "\"" || s == "'";

View File

@@ -36,7 +36,7 @@ class Quantity;
/**
* An individual schema object
*/
class UnitsSchema
class BaseExport UnitsSchema
{
public:
explicit UnitsSchema(UnitsSchemaSpec spec);

View File

@@ -30,6 +30,7 @@
#include "fmt/format.h"
#include "fmt/ranges.h"
#include "UnitsConvData.h"
#include "UnitsSchemasSpecs.h"
/**
@@ -42,6 +43,8 @@ namespace Base::UnitsSchemasData
constexpr std::size_t defDecimals {2};
constexpr std::size_t defDenominator {8};
using namespace Base::UnitsConvData;
// NOLINTBEGIN
// clang-format off
inline const UnitsSchemaSpec s0
@@ -69,15 +72,15 @@ inline const UnitsSchemaSpec s1
inline const UnitsSchemaSpec s2
{ 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 }}},
{ "Area", {{ 0 , "in^2" , 645.16 }}},
{ "Volume", {{ 0 , "in^3" , 16387.064 }}},
{ "Mass", {{ 0 , "lb" , 0.45359237 }}},
{ "Pressure", {{ 0 , "psi" , 6.894744825494 }}},
{ "Stiffness", {{ 0 , "lbf/in" , 4.448222 / 0.0254 }}},
{ "Velocity", {{ 0 , "in/min" , 25.4 / 60 }}},
{ "Acceleration", {{ 0 , "in/min^2", 25.4 / 3600 }}}
{ "Area", {{ 0 , "in^2" , in * in }}},
{ "Volume", {{ 0 , "in^3" , in * in * in }}},
{ "Mass", {{ 0 , "lb" , lb }}},
{ "Pressure", {{ 0 , "psi" , psi }}},
{ "Stiffness", {{ 0 , "lbf/in" , lbf / in * 1000 }}},
{ "Velocity", {{ 0 , "in/min" , in / 60 }}},
{ "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,
{
{ "Length", {
{ 0.00000254 , "in" , 25.4 },
{ 2.54 , "thou" , 0.0254 },
{ 304.8 , "\"" , 25.4 },
{ 914.4 , "'" , 304.8 },
{ 1'609'344.0 , "yd" , 914.4 },
{ 1'609'344'000.0 , "mi" , 1'609'344.0 },
{ 0 , "in" , 25.4 }}
{ 0.00000254 , "in" , in },
{ 2.54 , "thou" , in / 1000 },
{ 304.8 , "\"" , in },
{ 914.4 , "'" , ft },
{ 1'609'344.0 , "yd" , yd },
{ 1'609'344'000.0 , "mi" , mi },
{ 0 , "in" , in }}
},
{ "Angle", {
{ 0 , "°" , 1.0 }}
},
{ "Area", {
{ 0 , "in^2" , 645.16 }}
{ 0 , "in^2" , in * in }}
},
{ "Volume", {
{ 0 , "in^3" , 16'387.064 }}
{ 0 , "in^3" , in * in * in }}
},
{ "Mass", {
{ 0 , "lb" , 0.45359237 }}
{ 0 , "lb" , lb }}
},
{ "Pressure", {
{ 6'894.744 , "psi" , 6.894744825494 },
{ 6'894'744.825 , "ksi" , 6'894.744825494 },
{ 0 , "psi" , 6.894744825494 }}
{ 1000 * psi , "psi" , psi },
{ 1000000 * psi , "ksi" , 1000 * psi },
{ 0 , "psi" , psi }}
},
{ "Stiffness", {
{ 0 , "lbf/in" , 4.448222 / 0.0254 }}
{ 0 , "lbf/in" , lbf / in * 1000 }}
},
{ "Velocity", {
{ 0 , "in/min" , 25.4 / 60 }}
{ 0 , "in/min" , in / 60 }}
}
}
};
@@ -621,15 +624,22 @@ inline const UnitsSchemaSpec s8
{
{ "Length" , {{ 0 , "toFractional" , 0 }}}, // <== !
{ "Angle" , {{ 0 , "°" , 1.0 }}},
{ "Area" , {{ 0 , "sqft" , 92'903.04 }}},
{ "Volume" , {{ 0 , "cft" , 28'316'846.592 }}},
{ "Velocity" , {{ 0 , "in/min" , 25.4 / 60 }}}
{ "Area" , {{ 0 , "sqft" , ft * ft }}},
{ "Volume" , {{ 0 , "cft" , ft * ft * ft }}},
{ "Velocity" , {{ 0 , "in/min" , in / 60 }}}
}
};
inline const UnitsSchemaSpec s9
{ 7, "ImperialCivil", "ft", false, true, QT_TRANSLATE_NOOP("UnitsApi", "Imperial for Civil Eng (ft, ft/s)"), false,
{ 7, "ImperialCivil", "ft", false, true, QT_TRANSLATE_NOOP("UnitsApi", "Imperial for Civil Eng (ft, lb, mph)"), false,
{
{ "Length" , {{ 0 , "ft" , ft }}},
{ "Area" , {{ 0 , "ft^2" , ft * ft }}},
{ "Volume" , {{ 0 , "ft^3" , ft * ft * ft }}},
{ "Mass" , {{ 0 , "lb" , lb }}},
{ "Pressure" , {{ 0 , "psi" , psi }}},
{ "Stiffness", {{ 0 , "lbf/in", lbf / in * 1000 }}},
{ "Velocity" , {{ 0 , "mph" , mi / 3600 }}},
{ "Angle" , {{ 0 , "toDMS" , 0 }}} // <== !
}
};
@@ -654,27 +664,27 @@ inline std::size_t greatestCommonDenominator(const std::size_t a, const std::siz
/**
* double -> [feet'] [inches" [+ fraction]"], e.g.: 3' 4" + 3/8"
*/
inline std::string toFractional(const double value)
inline std::string toFractional(const double value, std::size_t denominator)
{
constexpr auto inchPerFoot {12};
constexpr auto mmPerInch {25.4};
auto numFractUnits =
static_cast<std::size_t>(std::round(std::abs(value) / mmPerInch * defDenominator));
static_cast<std::size_t>(std::round(std::abs(value) / mmPerInch * denominator));
if (numFractUnits == 0) {
return "0";
}
const auto feet =
static_cast<std::size_t>(std::floor(numFractUnits / (inchPerFoot * defDenominator)));
numFractUnits -= inchPerFoot * defDenominator * feet;
static_cast<std::size_t>(std::floor(numFractUnits / (inchPerFoot * denominator)));
numFractUnits -= inchPerFoot * denominator * feet;
const auto inches = static_cast<std::size_t>(std::floor(numFractUnits / defDenominator));
const std::size_t fractNumerator = numFractUnits - (defDenominator * inches);
const auto inches = static_cast<std::size_t>(std::floor(numFractUnits / denominator));
std::size_t numerator = numFractUnits - (denominator * inches);
const std::size_t common_denom = greatestCommonDenominator(fractNumerator, defDenominator);
const std::size_t numerator = fractNumerator / common_denom;
const std::size_t denominator = defDenominator / common_denom;
const std::size_t common_denom = greatestCommonDenominator(numerator, denominator);
numerator /= common_denom;
denominator /= common_denom;
bool addSpace {false};
std::string result;
@@ -737,33 +747,40 @@ inline std::string toDms(const double value)
*/
// clang-format off
inline const std::map<std::string, std::function<std::string(double, double&, std::string&)>> specials
inline const std::map<std::string, std::function<std::string(double, std::size_t, std::size_t, double&, std::string&)>> specials
{
{
{ "toDMS" , [](const double val, double& factor, std::string& unitString) {
{ "toDMS" , [](const double val, [[maybe_unused]] const std::size_t precision, [[maybe_unused]] const std::size_t denominator,
double& factor, std::string& unitString) {
factor = 1.0;
unitString = "deg";
return toDms(val);
}},
{ "toFractional" , [](const double val, double& factor, std::string& unitString) {
{ "toFractional" , [](const double val, [[maybe_unused]] const std::size_t precision, const std::size_t denominator,
double& factor, std::string& unitString) {
factor = 25.4;
unitString = "in";
return toFractional(val);
return toFractional(val, denominator);
}}
}
}; // clang-format on
inline std::string
runSpecial(const std::string& name, const double value, double& factor, std::string& unitString)
inline std::string runSpecial(const std::string& name,
const double value,
const std::size_t precision,
const std::size_t denominator,
double& factor,
std::string& unitString)
{
return specials.contains(name) ? specials.at(name)(value, factor, unitString) : "";
return specials.contains(name)
? specials.at(name)(value, precision, denominator, factor, unitString)
: "";
}
/**
* Build data pack
*/
inline const UnitsSchemasDataPack unitSchemasDataPack {schemaSpecs, defDecimals, defDenominator};

View File

@@ -563,13 +563,13 @@ QString InputField::getUnitText()
int InputField::getPrecision() const
{
return this->actQuantity.getFormat().precision;
return this->actQuantity.getFormat().getPrecision();
}
void InputField::setPrecision(const int precision)
{
Base::QuantityFormat format = actQuantity.getFormat();
format.precision = precision;
format.setPrecision(precision);
actQuantity.setFormat(format);
updateText(actQuantity);
}

View File

@@ -200,7 +200,7 @@ void DlgSettingsGeneral::saveUnitSystemSettings()
hGrpu->SetInt("FracInch", FracInch);
// Set the actual format value
QuantityFormat::setDefaultDenominator(FracInch);
UnitsApi::setDenominator(FracInch);
// Set and save the Unit System
if (ui->checkBox_projectUnitSystemIgnore->isChecked()) {
@@ -272,7 +272,7 @@ void DlgSettingsGeneral::loadSettings()
ui->checkBox_projectUnitSystemIgnore->setChecked(hGrpu->GetBool("IgnoreProjectSchema", false));
// Get the current user setting for the minimum fractional inch
FracInch = hGrpu->GetInt("FracInch", QuantityFormat::getDefaultDenominator());
FracInch = hGrpu->GetInt("FracInch", UnitsApi::getDenominator());
// Convert fractional inch to the corresponding combobox index using this
// handy little equation.
@@ -749,7 +749,8 @@ void DlgSettingsGeneral::onUnitSystemIndexChanged(const int index)
}
// Enable/disable the fractional inch option depending on system
const auto visible = UnitsApi::isMultiUnitLength();
const auto schema = UnitsApi::createSchema(index);
const auto visible = schema->isMultiUnitLength();
ui->comboBox_FracInch->setVisible(visible);
ui->fractionalInchLabel->setVisible(visible);
}

View File

@@ -742,14 +742,14 @@ bool QuantitySpinBox::isCheckedRangeInExpresion() const
int QuantitySpinBox::decimals() const
{
Q_D(const QuantitySpinBox);
return d->quantity.getFormat().precision;
return d->quantity.getFormat().getPrecision();
}
void QuantitySpinBox::setDecimals(int v)
{
Q_D(QuantitySpinBox);
Base::QuantityFormat f = d->quantity.getFormat();
f.precision = v;
f.setPrecision(v);
d->quantity.setFormat(f);
updateText(d->quantity);
}

View File

@@ -1187,7 +1187,7 @@ void PropertyUnitItem::setValue(const QVariant& value)
if (!hasExpression() && value.canConvert<Base::Quantity>()) {
const Base::Quantity& val = value.value<Base::Quantity>();
Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec);
setPropertyValue(Base::UnitsApi::toString(val, format));
setPropertyValue(val.toString(format));
}
}
@@ -1796,12 +1796,8 @@ void PropertyVectorDistanceItem::setValue(const QVariant& variant)
return;
}
const Base::Vector3d& value = variant.value<Base::Vector3d>();
Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec);
std::string val = fmt::format("({}, {}, {})",
Base::UnitsApi::toNumber(value.x, format),
Base::UnitsApi::toNumber(value.y, format),
Base::UnitsApi::toNumber(value.z, format));
std::string val = fmt::format("({:.{}g}, {:.{}g}, {:.{}g})",
value.x, highPrec, value.y, highPrec, value.z, highPrec);
setPropertyValue(val);
}
@@ -2536,12 +2532,9 @@ void PropertyRotationItem::setValue(const QVariant& value)
Base::Vector3d axis;
double angle {};
h.getValue(axis, angle);
Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec);
std::string val = fmt::format("App.Rotation(App.Vector({},{},{}),{})",
Base::UnitsApi::toNumber(axis.x, format),
Base::UnitsApi::toNumber(axis.y, format),
Base::UnitsApi::toNumber(axis.z, format),
Base::UnitsApi::toNumber(angle, format));
std::string val = fmt::format("App.Rotation(App.Vector({:.{}g},{:.{}g},{:.{}g}),{:.{}g})",
axis.x, highPrec, axis.y, highPrec, axis.z, highPrec,
angle, highPrec);
setPropertyValue(val);
}
@@ -2854,18 +2847,12 @@ void PropertyPlacementItem::setValue(const QVariant& value)
Base::Vector3d axis;
double angle {};
h.getValue(axis, angle);
Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec);
std::string str = fmt::format("App.Placement("
"App.Vector({},{},{}),"
"App.Rotation(App.Vector({},{},{}),{}))",
Base::UnitsApi::toNumber(pos.x, format),
Base::UnitsApi::toNumber(pos.y, format),
Base::UnitsApi::toNumber(pos.z, format),
Base::UnitsApi::toNumber(axis.x, format),
Base::UnitsApi::toNumber(axis.y, format),
Base::UnitsApi::toNumber(axis.z, format),
Base::UnitsApi::toNumber(angle, format));
"App.Vector({:.{}g},{:.{}g},{:.{}g}),"
"App.Rotation(App.Vector({:.{}g},{:.{}g},{:.{}g}),{:.{}g}))",
pos.x, highPrec, pos.y, highPrec, pos.z, highPrec,
axis.x, highPrec, axis.y, highPrec, axis.z, highPrec,
angle, highPrec);
setPropertyValue(str);
}

View File

@@ -29,7 +29,6 @@
#include <App/Document.h>
#include <Base/Interpreter.h>
#include <Base/PyObjectBase.h>
#include <Base/UnitsApi.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
@@ -132,9 +131,9 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.{0}.Length={1}\n"
"App.ActiveDocument.{0}.Width={2}\n"
"App.ActiveDocument.{0}.Height={3}\n", name,
Base::UnitsApi::toNumber(ui->boxLength->value()),
Base::UnitsApi::toNumber(ui->boxWidth->value()),
Base::UnitsApi::toNumber(ui->boxHeight->value()));
ui->boxLength->value().toNumber(),
ui->boxWidth->value().toNumber(),
ui->boxHeight->value().toNumber());
break;
case 1:
name = doc->getUniqueObjectName("Cylinder");
@@ -145,9 +144,9 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.{0}.EdgeLength={3}\n"
"App.ActiveDocument.{0}.Closed={4}\n"
"App.ActiveDocument.{0}.Sampling={5}\n", name,
Base::UnitsApi::toNumber(ui->cylinderRadius->value()),
Base::UnitsApi::toNumber(ui->cylinderLength->value()),
Base::UnitsApi::toNumber(ui->cylinderEdgeLength->value()),
ui->cylinderRadius->value().toNumber(),
ui->cylinderLength->value().toNumber(),
ui->cylinderEdgeLength->value().toNumber(),
ui->cylinderClosed->isChecked() ? "True" : "False",
ui->cylinderCount->value());
break;
@@ -161,10 +160,10 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.{0}.EdgeLength={4}\n"
"App.ActiveDocument.{0}.Closed={5}\n"
"App.ActiveDocument.{0}.Sampling={6}\n", name,
Base::UnitsApi::toNumber(ui->coneRadius1->value()),
Base::UnitsApi::toNumber(ui->coneRadius2->value()),
Base::UnitsApi::toNumber(ui->coneLength->value()),
Base::UnitsApi::toNumber(ui->coneEdgeLength->value()),
ui->coneRadius1->value().toNumber(),
ui->coneRadius2->value().toNumber(),
ui->coneLength->value().toNumber(),
ui->coneEdgeLength->value().toNumber(),
ui->coneClosed->isChecked() ? "True" : "False",
ui->coneCount->value());
break;
@@ -174,7 +173,7 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.addObject(\"Mesh::Sphere\",\"{0}\")\n"
"App.ActiveDocument.{0}.Radius={1}\n"
"App.ActiveDocument.{0}.Sampling={2}\n", name,
Base::UnitsApi::toNumber(ui->sphereRadius->value()),
ui->sphereRadius->value().toNumber(),
ui->sphereCount->value());
break;
case 4:
@@ -184,8 +183,8 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.{0}.Radius1={1}\n"
"App.ActiveDocument.{0}.Radius2={2}\n"
"App.ActiveDocument.{0}.Sampling={3}\n", name,
Base::UnitsApi::toNumber(ui->ellipsoidRadius1->value()),
Base::UnitsApi::toNumber(ui->ellipsoidRadius2->value()),
ui->ellipsoidRadius1->value().toNumber(),
ui->ellipsoidRadius2->value().toNumber(),
ui->ellipsoidCount->value());
break;
case 5:
@@ -195,8 +194,8 @@ void DlgRegularSolidImp::onCreateSolidButtonClicked()
"App.ActiveDocument.{0}.Radius1={1}\n"
"App.ActiveDocument.{0}.Radius2={2}\n"
"App.ActiveDocument.{0}.Sampling={3}\n", name,
Base::UnitsApi::toNumber(ui->toroidRadius1->value()),
Base::UnitsApi::toNumber(ui->toroidRadius2->value()),
ui->toroidRadius1->value().toNumber(),
ui->toroidRadius2->value().toNumber(),
ui->toroidCount->value());
break;
}

View File

@@ -136,7 +136,7 @@ Quantity Constraint::getPresentationValue() const
QuantityFormat format = quantity.getFormat();
format.option = QuantityFormat::None;
format.format = QuantityFormat::Default;
format.precision = 6; // QString's default
format.setPrecision(6); // QString's default
quantity.setFormat(format);
return quantity;
}

View File

@@ -198,25 +198,25 @@ protected:
TEST_F(BaseQuantityLoc, psi_parse_spaced)
{
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)
{
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)
{
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)
{
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)
@@ -228,7 +228,7 @@ TEST_F(BaseQuantityLoc, psi_parse_unit_type)
TEST_F(BaseQuantityLoc, psi_to_Pa)
{
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::Pascal);
const auto expect = 6894.7448254939991;
const auto expect = 6894.7572931683608;
EXPECT_EQ(result, expect);
}
@@ -236,7 +236,7 @@ TEST_F(BaseQuantityLoc, psi_to_Pa)
TEST_F(BaseQuantityLoc, psi_to_KPa)
{
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::KiloPascal);
const auto expect = 6.8947448254939996;
const auto expect = 6.8947572931683609;
EXPECT_EQ(result, expect);
}
@@ -244,7 +244,7 @@ TEST_F(BaseQuantityLoc, psi_to_KPa)
TEST_F(BaseQuantityLoc, psi_to_MPa)
{
const auto result = Quantity::parse("1 psi").getValueAs(Quantity::MegaPascal);
const auto expect = 0.0068947448254939999;
const auto expect = 0.0068947572931683607;
EXPECT_EQ(result, expect);
}

View File

@@ -69,7 +69,7 @@ protected:
UnitsApi::setSchema(name);
Quantity quantity {value, unit};
QuantityFormat format = quantity.getFormat();
format.precision = precision;
format.setPrecision(precision);
quantity.setFormat(format);
return quantity.getSafeUserString();
}
@@ -298,7 +298,7 @@ TEST_F(SchemaTest, imperial_decimal_0_mm_precision_1)
TEST_F(SchemaTest, imperial_civil_0_mm_precision_0)
{
const std::string result = setWithPrecision("ImperialCivil", 0.0, Unit::Length, 0);
const auto expect {"0 mm"};
const auto expect {"0 ft"};
EXPECT_EQ(result, expect);
}
@@ -306,7 +306,7 @@ TEST_F(SchemaTest, imperial_civil_0_mm_precision_0)
TEST_F(SchemaTest, imperial_civil_0_mm_precision_1)
{
const std::string result = setWithPrecision("ImperialCivil", 0.0, Unit::Length, 1);
const auto expect {"0.0 mm"};
const auto expect {"0.0 ft"};
EXPECT_EQ(result, expect);
}

View File

@@ -51,18 +51,18 @@ private Q_SLOTS:
{
auto quant = qsb->value();
auto format = quant.getFormat();
format.precision = 7;
format.setPrecision(7);
quant.setFormat(format);
qsb->setValue(quant);
auto val1 = qsb->value();
QCOMPARE(val1.getFormat().precision, 7);
QCOMPARE(val1.getFormat().getPrecision(), 7);
// format shouldn't change after setting a double
qsb->setValue(3.5);
auto val2 = qsb->value();
QCOMPARE(val2.getFormat().precision, 7);
QCOMPARE(val2.getFormat().getPrecision(), 7);
}
private: