From eb5cc8ed6cd8d911c5418e22ec0b1f20061fdaff Mon Sep 17 00:00:00 2001 From: jriegel Date: Thu, 5 Dec 2013 18:16:31 +0100 Subject: [PATCH] Implement the three major unit system schemas --- src/Base/Quantity.cpp | 1 + src/Base/Quantity.h | 1 + src/Base/QuantityParser.l | 4 +- src/Base/QuantityPyImp.cpp | 3 +- src/Base/Unit.cpp | 3 + src/Base/Unit.h | 3 + src/Base/UnitsApi.cpp | 7 ++- src/Base/UnitsApiPy.cpp | 5 ++ src/Base/UnitsSchema.h | 8 +++ src/Base/UnitsSchemaImperial1.cpp | 93 +++++++++++++++++++++++++------ src/Base/UnitsSchemaImperial1.h | 2 + src/Base/UnitsSchemaInternal.cpp | 72 ++++++++++++++++++------ src/Base/UnitsSchemaMKS.cpp | 67 +++++++++++++++++----- src/Gui/DlgSettingsUnits.ui | 2 +- 14 files changed, 220 insertions(+), 51 deletions(-) diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index e92ee8667..412507a2e 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -213,6 +213,7 @@ Quantity Quantity::MegaPascal (1000.0 ,Unit(-1,1,-2)); Quantity Quantity::GigaPascal (1e+6 ,Unit(-1,1,-2)); Quantity Quantity::PSI (0.145038 ,Unit(-1,1,-2)); // pounds/in^2 +Quantity Quantity::KSI (145.038 ,Unit(-1,1,-2)); // 1000 x pounds/in^2 Quantity Quantity::Watt (1e+6 ,Unit(2,1,-3)); // Watt (kg*m^2/s^3) Quantity Quantity::VoltAmpere (1e+6 ,Unit(2,1,-3)); // VoltAmpere (kg*m^2/s^3) diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h index 4d66c24f0..4dbfd93bd 100644 --- a/src/Base/Quantity.h +++ b/src/Base/Quantity.h @@ -155,6 +155,7 @@ public: static Quantity GigaPascal; static Quantity PSI; + static Quantity KSI; static Quantity Watt; static Quantity VoltAmpere; diff --git a/src/Base/QuantityParser.l b/src/Base/QuantityParser.l index eee575546..af169a092 100644 --- a/src/Base/QuantityParser.l +++ b/src/Base/QuantityParser.l @@ -74,7 +74,8 @@ ID [a-z][a-z0-9]* "\"" yylval = Quantity::Inch; return UNIT; // inch "fo" yylval = Quantity::Foot; return UNIT; // foot "'" yylval = Quantity::Foot; return UNIT; // foot - "th" yylval = Quantity::Thou; return UNIT; // thou + "thou" yylval = Quantity::Thou; return UNIT; // thou (in/1000) + "mil" yylval = Quantity::Thou; return UNIT; // mil (the thou in US) "yr" yylval = Quantity::Yard; return UNIT; // yard "mi" yylval = Quantity::Mile; return UNIT; // mile @@ -96,6 +97,7 @@ ID [a-z][a-z0-9]* "GPa" yylval = Quantity::GigaPascal; return UNIT; // Pascal "psi" yylval = Quantity::PSI; return UNIT; // pounds/in^2 + "ksi" yylval = Quantity::KSI; return UNIT; // 1000 x pounds/in^2 "W" yylval = Quantity::Watt; return UNIT; // Watt (kg*m^2/s^3) "VA" yylval = Quantity::VoltAmpere; return UNIT; // VoltAmpere (kg*m^2/s^3) diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index 3f4f699b8..e3c6085a0 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -207,8 +207,7 @@ void QuantityPy::setUnit(Py::Object arg) Py::String QuantityPy::getUserString(void) const { - //return Py::String(); - throw Py::AttributeError("Not yet implemented"); + return Py::String(getQuantityPtr()->getUserString().toLatin1()); } PyObject *QuantityPy::getCustomAttributes(const char* /*attr*/) const diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index 109e9d009..4db9862ee 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -331,3 +331,6 @@ Unit Unit::Temperature(0,0,0,0,1); Unit Unit::ElectricCurrent(0,0,0,1); Unit Unit::AmountOfSubstance(0,0,0,0,0,1); Unit Unit::LuminoseIntensity(0,0,0,0,0,0,1); + +Unit Unit::Stress (-1,1,-2); // kg/m*s^2 or N/m^2 or PSI +Unit Unit::Pressure(-1,1,-2); // kg/m*s^2 or N/m^2 or PSI diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 5c72a47ac..5e7368150 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -94,6 +94,9 @@ public: static Unit ElectricCurrent; static Unit AmountOfSubstance; static Unit LuminoseIntensity; + + static Unit Stress; + static Unit Pressure; //@} protected: UnitSignature Sig; diff --git a/src/Base/UnitsApi.cpp b/src/Base/UnitsApi.cpp index 1eb520885..3693ca350 100644 --- a/src/Base/UnitsApi.cpp +++ b/src/Base/UnitsApi.cpp @@ -79,13 +79,16 @@ UnitsApi::~UnitsApi() void UnitsApi::setSchema(UnitSystem s) { - delete UserPrefSystem; + if(UserPrefSystem){ + UserPrefSystem->resetSchemaUnits(); // for schemas changed the Quantity constants + delete UserPrefSystem; + } switch (s) { case SI1 : UserPrefSystem = new UnitsSchemaInternal(); break; case SI2 : UserPrefSystem = new UnitsSchemaMKS(); break; case Imperial1: UserPrefSystem = new UnitsSchemaImperial1(); break; } - //UserPrefSystem->setSchemaUnits(); + UserPrefSystem->setSchemaUnits(); // if necesarry a unit schema can change the constants in Quantity (e.g. mi=1.8km rather then 1.6km). } diff --git a/src/Base/UnitsApiPy.cpp b/src/Base/UnitsApiPy.cpp index caf0e8bb6..da761a5e2 100644 --- a/src/Base/UnitsApiPy.cpp +++ b/src/Base/UnitsApiPy.cpp @@ -70,6 +70,11 @@ PyMethodDef UnitsApi::Methods[] = { //}, {"parseQuantity", (PyCFunction) UnitsApi::sParseQuantity ,1, "parseQuantity(string) -> Base.Quantity()\n\n" + "calculate a mathematical expression with units to a quantity object. \n" + "can be used for simple unit translation like: \n" + " parseQuantity('10m')\n" + " or for more complex espressions:\n" + " parseQuantity('sin(pi)/50.0 m/s^2')\n" }, {NULL, NULL, 0, NULL} /* Sentinel */ diff --git a/src/Base/UnitsSchema.h b/src/Base/UnitsSchema.h index fb07dc172..26ecc5ca7 100644 --- a/src/Base/UnitsSchema.h +++ b/src/Base/UnitsSchema.h @@ -49,6 +49,14 @@ enum UnitSystem { class UnitsSchema { public: + /** get called if this schema gets activated. + * Here its theoretical possible that you can change the static factors + * for certain Units (e.g. mi = 1,8km instead of mi=1.6km). + */ + virtual void setSchemaUnits(void){} + /// if you use setSchemaUnits() you have also to impment this methode to undo your changes! + virtual void resetSchemaUnits(void){} + /// this methode translate the quantity in a string as the user may expect it virtual QString schemaTranslate(Base::Quantity quant,double &factor,QString &unitString)=0; }; diff --git a/src/Base/UnitsSchemaImperial1.cpp b/src/Base/UnitsSchemaImperial1.cpp index 343d635e6..1260bae38 100644 --- a/src/Base/UnitsSchemaImperial1.cpp +++ b/src/Base/UnitsSchemaImperial1.cpp @@ -34,25 +34,86 @@ using namespace Base; + +//void UnitsSchemaImperial1::setSchemaUnits(void){ +// // here you could change the constances used by the parser (defined in Quantity.cpp) +// Quantity::Inch = Quantity (25.4 ,Unit(1)); +// Quantity::Foot = Quantity (304.8 ,Unit(1)); +// Quantity::Thou = Quantity (0.0254 ,Unit(1)); +// Quantity::Yard = Quantity (914.4 ,Unit(1)); +// Quantity::Mile = Quantity (1609344.0 ,Unit(1)); +//} +// +//void UnitsSchemaImperial1::resetSchemaUnits(void){ +// // set units to US customary / Imperial units +// Quantity::Inch = Quantity (25.4 ,Unit(1)); +// Quantity::Foot = Quantity (304.8 ,Unit(1)); +// Quantity::Thou = Quantity (0.0254 ,Unit(1)); +// Quantity::Yard = Quantity (914.4 ,Unit(1)); +// Quantity::Mile = Quantity (1609344.0 ,Unit(1)); +//} + QString UnitsSchemaImperial1::schemaTranslate(Base::Quantity quant,double &factor,QString &unitString) { double UnitValue = quant.getValue(); Unit unit = quant.getUnit(); + // for imperial user/programmer mind; UnitValue is in internal system, that means + // mm/kg/s. And all combined units have to be calculated from there! - return QString::fromAscii("%1 %2").arg(UnitValue).arg(QString::fromAscii(unit.getString().c_str())); + // now do special treatment on all cases seams nececarry: + if(unit == Unit::Length){ // Length handling ============================ + if(UnitValue < 0.00000254){// smaller then 0.001 thou -> inch and scientific notation + unitString = QString::fromLatin1("in"); + factor = 25.4; + }else if(UnitValue < 2.54){ // smaller then 0.1 inch -> Thou (mil) + unitString = QString::fromLatin1("thou"); + factor = 0.0254; + }else if(UnitValue < 304.8){ + unitString = QString::fromLatin1("in"); + factor = 25.4; + }else if(UnitValue < 914.4){ + unitString = QString::fromLatin1("ft"); + factor = 304.8; + }else if(UnitValue < 1609344.0){ + unitString = QString::fromLatin1("yr"); + factor = 914.4; + }else if(UnitValue < 1609344000.0 ){ + unitString = QString::fromLatin1("mi"); + factor = 1609344.0; + }else{ // bigger then 1000 mi -> scientific notation + unitString = QString::fromLatin1("in"); + factor = 25.4; + } + }else if (unit == Unit::Area){ + // TODO Cascade for the Areas + // default action for all cases without special treatment: + unitString = QString::fromLatin1("in^2"); + factor = 645.16; + }else if (unit == Unit::Volume){ + // TODO Cascade for the Volume + // default action for all cases without special treatment: + unitString = QString::fromLatin1("in^3"); + factor = 16387.1; + }else if (unit == Unit::Mass){ + // TODO Cascade for the wights + // default action for all cases without special treatment: + unitString = QString::fromLatin1("lb"); + factor = 0.45359237; + }else if (unit == Unit::Pressure){ + if(UnitValue < 145.038){// psi is the smallest + unitString = QString::fromLatin1("psi"); + factor = 0.145038; + }else if(UnitValue < 145038){ + unitString = QString::fromLatin1("ksi"); + factor = 145.038; + }else{ // bigger then 1000 ksi -> psi + scientific notation + unitString = QString::fromLatin1("psi"); + factor = 0.145038; + } + }else{ + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + } + return QString::fromLatin1("%1 %2").arg(UnitValue / factor).arg(unitString); } -// -//Base::Quantity UnitsSchemaImperial1::schemaPrefUnit(const Base::Unit &unit,QString &outUnitString) -//{ -// if(unit == Unit::Length){ -// outUnitString = QString::fromAscii("\""); -// return Base::Quantity(1/25.40,Unit::Length); -// }else if(unit == Unit::Mass){ -// outUnitString = QString::fromAscii("lb"); -// return Base::Quantity(1/0.45359237,Unit::Length); -// }else{ -// outUnitString = QString::fromAscii(unit.getString().c_str()); -// return Base::Quantity(1,unit); -// } -// -//} \ No newline at end of file diff --git a/src/Base/UnitsSchemaImperial1.h b/src/Base/UnitsSchemaImperial1.h index 2f08d6997..a88557ebd 100644 --- a/src/Base/UnitsSchemaImperial1.h +++ b/src/Base/UnitsSchemaImperial1.h @@ -39,6 +39,8 @@ namespace Base { class UnitsSchemaImperial1: public UnitsSchema { public: + //virtual void setSchemaUnits(void); + //virtual void resetSchemaUnits(void); virtual QString schemaTranslate(Base::Quantity quant,double &factor,QString &unitString); }; diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index 62463e84f..6c1ea503b 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -38,20 +38,60 @@ QString UnitsSchemaInternal::schemaTranslate(Base::Quantity quant,double &factor { double UnitValue = quant.getValue(); Unit unit = quant.getUnit(); - // sending back the choosen values: - unitString = QString::fromAscii(quant.getUnit().getString().c_str()); - factor = 1.0; - return QString::fromAscii("%1 %2").arg(UnitValue).arg(QString::fromAscii(unit.getString().c_str())); -} -// -//Base::Quantity UnitsSchemaInternal::schemaPrefUnit(const Base::Unit &unit,QString &outUnitString) -//{ -// if(unit == Unit::Length){ -// outUnitString = QString::fromAscii("mm"); -// return Base::Quantity(1.0,Unit::Length); -// }else{ -// outUnitString = QString::fromAscii(unit.getString().c_str()); -// return Base::Quantity(1,unit); -// } -//} + // now do special treatment on all cases seams nececarry: + if(unit == Unit::Length){ // Length handling ============================ + if(UnitValue < 0.000000001){// smaller then 0.001 nm -> scientific notation + unitString = QString::fromLatin1("mm"); + factor = 1.0; + }else if(UnitValue < 0.001){ + unitString = QString::fromLatin1("nm"); + factor = 0.000001; + }else if(UnitValue < 1.0){ + unitString = QString::fromLatin1("ym"); + factor = 0.001; + }else if(UnitValue < 10000.0){ + unitString = QString::fromLatin1("mm"); + factor = 1.0; + }else if(UnitValue < 10000000.0){ + unitString = QString::fromLatin1("m"); + factor = 10000.0; + }else if(UnitValue < 100000000000.0 ){ + unitString = QString::fromLatin1("km"); + factor = 10000000.0; + }else{ // bigger then 1000 km -> scientific notation + unitString = QString::fromLatin1("mm"); + factor = 1.0; + } + }else if (unit == Unit::Area){ + // TODO Cascade for the Areas + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + }else if (unit == Unit::Mass){ + // TODO Cascade for the wights + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + }else if (unit == Unit::Pressure){ + if(UnitValue < 10.0){// Pa is the smallest + unitString = QString::fromLatin1("Pa"); + factor = 0.001; + }else if(UnitValue < 10000.0){ + unitString = QString::fromLatin1("kPa"); + factor = 1.0; + }else if(UnitValue < 10000000.0){ + unitString = QString::fromLatin1("GPa"); + factor = 1000.0; + }else{ // bigger then 1000 GPa -> scientific notation + unitString = QString::fromLatin1("Pa"); + factor = 1.0; + } + }else{ + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + } + return QString::fromLatin1("%1 %2").arg(UnitValue / factor).arg(unitString); +} + diff --git a/src/Base/UnitsSchemaMKS.cpp b/src/Base/UnitsSchemaMKS.cpp index ca45eaafd..cc3fecf7e 100644 --- a/src/Base/UnitsSchemaMKS.cpp +++ b/src/Base/UnitsSchemaMKS.cpp @@ -39,17 +39,58 @@ QString UnitsSchemaMKS::schemaTranslate(Base::Quantity quant,double &factor,QStr double UnitValue = quant.getValue(); Unit unit = quant.getUnit(); - return QString::fromAscii("%1 %2").arg(UnitValue).arg(QString::fromAscii(unit.getString().c_str())); + // now do special treatment on all cases seams nececarry: + if(unit == Unit::Length){ // Length handling ============================ + if(UnitValue < 0.000000001){// smaller then 0.001 nm -> scientific notation + unitString = QString::fromLatin1("mm"); + factor = 1.0; + }else if(UnitValue < 0.001){ + unitString = QString::fromLatin1("nm"); + factor = 0.000001; + }else if(UnitValue < 1.0){ + unitString = QString::fromLatin1("ym"); + factor = 0.001; + }else if(UnitValue < 100.0){ + unitString = QString::fromLatin1("mm"); + factor = 1.0; + }else if(UnitValue < 10000000.0){ + unitString = QString::fromLatin1("m"); + factor = 1000.0; + }else if(UnitValue < 100000000000.0 ){ + unitString = QString::fromLatin1("km"); + factor = 10000000.0; + }else{ // bigger then 1000 km -> scientific notation + unitString = QString::fromLatin1("mm"); + factor = 1.0; + } + }else if (unit == Unit::Area){ + // TODO Cascade for the Areas + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + }else if (unit == Unit::Mass){ + // TODO Cascade for the wights + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + }else if (unit == Unit::Pressure){ + if(UnitValue < 10.0){// Pa is the smallest + unitString = QString::fromLatin1("Pa"); + factor = 0.001; + }else if(UnitValue < 10000.0){ + unitString = QString::fromLatin1("kPa"); + factor = 1.0; + }else if(UnitValue < 10000000.0){ + unitString = QString::fromLatin1("GPa"); + factor = 1000.0; + }else{ // bigger then 1000 GPa -> scientific notation + unitString = QString::fromLatin1("Pa"); + factor = 1.0; + } + }else{ + // default action for all cases without special treatment: + unitString = QString::fromLatin1(quant.getUnit().getString().c_str()); + factor = 1.0; + } + return QString::fromLatin1("%1 %2").arg(UnitValue / factor).arg(unitString); } -// -//Base::Quantity UnitsSchemaMKS::schemaPrefUnit(const Base::Unit &unit,QString &outUnitString) -//{ -// if(unit == Unit::Length){ -// outUnitString = QString::fromAscii("m"); -// return Base::Quantity(1/1000.0,Unit::Length); -// }else{ -// outUnitString = QString::fromAscii(unit.getString().c_str()); -// return Base::Quantity(1,unit); -// } -// -//} \ No newline at end of file diff --git a/src/Gui/DlgSettingsUnits.ui b/src/Gui/DlgSettingsUnits.ui index 05c16b79c..8a2d524e8 100644 --- a/src/Gui/DlgSettingsUnits.ui +++ b/src/Gui/DlgSettingsUnits.ui @@ -43,7 +43,7 @@ - Imperial (in/lb) + US customary (in/lb)