From a0917bcc7cf48961d25a0cf14fdb305523cc8669 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 10 Apr 2025 19:15:02 +0200 Subject: [PATCH] Base: Units: introduce unit one Dimensionless quantities have all exponents equal to zero. Such quantities are simply numbers. The associated unit is the unit one, symbol 1, although this is rarely explicitly written. See chapter 2.3.3 Dimensions of quantities, The International System of Units, 9th edition. --- src/App/PropertyGeo.cpp | 4 ++-- src/Base/Quantity.cpp | 4 ++-- src/Base/Unit.cpp | 14 ++++++++------ src/Base/Unit.h | 7 ++----- src/Gui/Dialogs/DlgExpressionInput.cpp | 2 +- src/Gui/InputField.cpp | 2 +- src/Mod/Spreadsheet/App/Cell.cpp | 4 ++-- src/Mod/Spreadsheet/App/Sheet.cpp | 2 +- src/Mod/Spreadsheet/Gui/SheetModel.cpp | 2 +- tests/src/Base/Unit.cpp | 2 +- 10 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index c4a51c4419..ad857a41d0 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -194,7 +194,7 @@ void PropertyVector::getPaths(std::vector& 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; } diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index babbe4a4c2..a9c6fcb467 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -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 myUnit.isEmpty(); + return myUnit == Unit::One; } /// true if it has a specific unit or no dimension. diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index baa782972d..8b8570879a 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -281,11 +281,6 @@ int Unit::angle() const return sig.Angle; } -bool Unit::isEmpty() const -{ - return Val == 0; -} - int Unit::operator [](int index) const { UnitSignature sig; @@ -318,6 +313,11 @@ bool Unit::operator ==(const Unit& that) const return Val == that.Val; } +bool Unit::operator !=(const Unit& that) const +{ + return Val != that.Val; +} + Unit Unit::operator *(const Unit &right) const { Unit result; @@ -360,7 +360,7 @@ Unit Unit::operator /(const Unit &right) const std::string Unit::getString() const { - if (isEmpty()) { + if (Val == 0) { return {}; } @@ -658,6 +658,8 @@ std::string Unit::getTypeString() const return spec->second; } +const Unit Unit::One (0, 0, 0, 0, 0, 0, 0, 0); + // SI base units const Unit Unit::AmountOfSubstance (0, 0, 0, 0, 0, 1); const Unit Unit::ElectricCurrent (0, 0, 0, 1); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 77b2273b3d..f5e6197bf2 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -61,10 +61,7 @@ public: Unit operator*(const Unit&) const; Unit operator/(const Unit&) const; bool operator==(const Unit&) const; - bool operator!=(const Unit& that) const - { - return !(*this == that); - } + bool operator!=(const Unit& that) const; Unit& operator=(const Unit&) = default; Unit& operator=(Unit&&) = default; Unit pow(double exp) const; @@ -79,7 +76,6 @@ public: 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". @@ -87,6 +83,7 @@ public: /** Predefined Unit types. */ //@{ + static const Unit One; /// Length unit static const Unit Length; /// Mass unit diff --git a/src/Gui/Dialogs/DlgExpressionInput.cpp b/src/Gui/Dialogs/DlgExpressionInput.cpp index b8ee7c36b1..e626ab7cb3 100644 --- a/src/Gui/Dialogs/DlgExpressionInput.cpp +++ b/src/Gui/Dialogs/DlgExpressionInput.cpp @@ -294,7 +294,7 @@ void DlgExpressionInput::checkExpression(const QString& text) } auto msg = value.getUserString(); - if (!impliedUnit.isEmpty()) { + if (impliedUnit != Base::Unit::One) { if (!value.isDimensionless() && value.getUnit() != impliedUnit) throw Base::UnitsMismatchError("Unit mismatch between result and required unit"); diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index d6ca20d1a3..ed418866a3 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -282,7 +282,7 @@ void InputField::newInput(const QString & text) res.setUnit(this->actUnit); // check if unit fits! - if (!actUnit.isEmpty() && !res.isDimensionless() && actUnit != res.getUnit()){ + if (actUnit != Unit::One && !res.isDimensionless() && actUnit != res.getUnit()){ if (iconLabel->isHidden()) { iconLabel->setVisible(true); } diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp index 324ff7bb61..9668a52d14 100644 --- a/src/Mod/Spreadsheet/App/Cell.cpp +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -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); diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp index e2253da0cd..eb4fea54c5 100644 --- a/src/Mod/Spreadsheet/App/Sheet.cpp +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -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)) { diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp index 9f097aac73..befa29c199 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -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', diff --git a/tests/src/Base/Unit.cpp b/tests/src/Base/Unit.cpp index fa73d91106..b34386d935 100644 --- a/tests/src/Base/Unit.cpp +++ b/tests/src/Base/Unit.cpp @@ -121,7 +121,7 @@ TEST(Unit, TestPowNoDim) { Base::Unit unit {}; EXPECT_EQ(unit.pow(2), Base::Unit {0}); - EXPECT_EQ(unit.isEmpty(), true); + EXPECT_EQ(unit == Base::Unit::One, true); } TEST(Unit, TestPowEQ1)