diff --git a/src/Base/UnitsApi.cpp b/src/Base/UnitsApi.cpp index 934c75433d..f51d56e8e3 100644 --- a/src/Base/UnitsApi.cpp +++ b/src/Base/UnitsApi.cpp @@ -80,6 +80,50 @@ UnitsApi::~UnitsApi() { } +const char* UnitsApi::getDescription(UnitSystem system) +{ + switch (system) { + case SI1: + return "Standard (mm/kg/s/degree)"; + case SI2: + return "MKS (m/kg/s/degree)"; + case Imperial1: + return "US customary (in/lb)"; + case ImperialDecimal: + return "Imperial decimal (in/lb)"; + case Centimeters: + return "Building Euro (cm/m²/m³)"; + case ImperialBuilding: + return "Building US (ft-in/sqft/cuft)"; + case MmMin: + return "Metric small parts & CNC(mm, mm/min)"; + default: + return "Unknown schema"; + } +} + +UnitsSchema* UnitsApi::createSchema(UnitSystem s) +{ + switch (s) { + case SI1: + return new UnitsSchemaInternal(); + case SI2: + return new UnitsSchemaMKS(); + case Imperial1: + return new UnitsSchemaImperial1(); + case ImperialDecimal: + return new UnitsSchemaImperialDecimal(); + case Centimeters: + return new UnitsSchemaCentimeters(); + case ImperialBuilding: + return new UnitsSchemaImperialBuilding(); + case MmMin: + return new UnitsSchemaMmMin(); + } + + return 0; +} + void UnitsApi::setSchema(UnitSystem s) { if (UserPrefSystem) { @@ -87,18 +131,16 @@ void UnitsApi::setSchema(UnitSystem s) delete UserPrefSystem; UserPrefSystem = 0; } - switch (s) { - case SI1 : UserPrefSystem = new UnitsSchemaInternal(); break; - case SI2 : UserPrefSystem = new UnitsSchemaMKS(); break; - case Imperial1: UserPrefSystem = new UnitsSchemaImperial1(); break; - case ImperialDecimal: UserPrefSystem = new UnitsSchemaImperialDecimal(); break; - case Centimeters: UserPrefSystem = new UnitsSchemaCentimeters(); break; - case ImperialBuilding: UserPrefSystem = new UnitsSchemaImperialBuilding(); break; - case MmMin: UserPrefSystem = new UnitsSchemaMmMin(); break; - default : UserPrefSystem = new UnitsSchemaInternal(); s = SI1; break; + + UserPrefSystem = createSchema(s); + actSystem = s; + + // for wrong value fall back to standard schema + if (!UserPrefSystem) { + UserPrefSystem = new UnitsSchemaInternal(); + actSystem = SI1; } - actSystem = s; 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/UnitsApi.h b/src/Base/UnitsApi.h index 03d504e6ff..9b36f65476 100644 --- a/src/Base/UnitsApi.h +++ b/src/Base/UnitsApi.h @@ -55,6 +55,8 @@ public: static void setSchema(UnitSystem s); /// return the active schema static UnitSystem getSchema(void){return actSystem;} + /// Returns a brief description of a schema + static const char* getDescription(UnitSystem); static QString schemaTranslate(const Base::Quantity& quant, double &factor, QString &unitString); static QString schemaTranslate(const Base::Quantity& quant) { // to satisfy GCC @@ -62,6 +64,7 @@ public: QString dummy2; return UnitsApi::schemaTranslate(quant, dummy1, dummy2); } + /// generate a value for a quantity with default user preferred system static double toDbl(PyObject *ArgObj,const Base::Unit &u=Base::Unit()); /// generate a value for a quantity with default user preferred system @@ -82,6 +85,9 @@ public: static double defaultFactor; +protected: + /// return an instance of the given enum value + static UnitsSchema* createSchema(UnitSystem s); protected: // not used at the moment @@ -97,6 +103,9 @@ protected: // the python API wrapper methodes //static PyObject *sTranslateUnit (PyObject *self,PyObject *args,PyObject *kwd); //static PyObject *sGetWithPrefs (PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sParseQuantity (PyObject *self,PyObject *args,PyObject *kwd); + static PyObject *sListSchemas (PyObject *self,PyObject *args,PyObject *kwd); + static PyObject *sGetSchema (PyObject *self,PyObject *args,PyObject *kwd); + static PyObject *sSchemaTranslate (PyObject *self,PyObject *args,PyObject *kwd); }; } // namespace Base diff --git a/src/Base/UnitsApiPy.cpp b/src/Base/UnitsApiPy.cpp index c3c7ff6d8a..159e387ff1 100644 --- a/src/Base/UnitsApiPy.cpp +++ b/src/Base/UnitsApiPy.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include #endif #include @@ -68,12 +69,24 @@ 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" + "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" + }, + {"listSchemas", (PyCFunction) UnitsApi::sListSchemas ,1, + "listSchemas() -> a tuple of schemas\n\n" + "listSchemas(int) -> description of the given schema\n\n" + }, + {"getSchema", (PyCFunction) UnitsApi::sGetSchema ,1, + "getSchema() -> int\n\n" + "The int is the position of the tuple returned by listSchemas" + }, + {"schemaTranslate", (PyCFunction) UnitsApi::sSchemaTranslate ,1, + "schemaTranslate(Quantity, int) -> tuple\n\n" + "Translate a quantity to a given schema" }, {NULL, NULL, 0, NULL} /* Sentinel */ @@ -148,3 +161,67 @@ PyObject* UnitsApi::sParseQuantity(PyObject * /*self*/, PyObject *args,PyObject return new QuantityPy(new Quantity(rtn)); } + +PyObject* UnitsApi::sListSchemas(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + if (PyArg_ParseTuple(args, "")) { + int num = NumUnitSystemTypes; + Py::Tuple tuple(num); + for (int i=0; i(i)))); + } + + return Py::new_reference_to(tuple); + } + + PyErr_Clear(); + int index; + if (PyArg_ParseTuple(args, "i", &index)) { + int num = NumUnitSystemTypes; + if (index < 0 || index >= num) { + PyErr_SetString(PyExc_ValueError, "invalid schema value"); + return 0; + } + + return Py_BuildValue("s", UnitsApi::getDescription(static_cast(index))); + } + + PyErr_SetString(PyExc_TypeError, "int or empty argument list expected"); + return 0; +} + +PyObject* UnitsApi::sGetSchema(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + return Py_BuildValue("i", static_cast(actSystem)); +} + +PyObject* UnitsApi::sSchemaTranslate(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + PyObject* q; + int index; + if (!PyArg_ParseTuple(args, "O!i", &(QuantityPy::Type), &q, &index)) + return 0; + + Quantity quant; + quant = *static_cast(q)->getQuantityPtr(); + + std::unique_ptr schema(createSchema(static_cast(index))); + if (!schema) { + PyErr_SetString(PyExc_ValueError, "invalid schema value"); + return 0; + } + + double factor; + QString uus; + QString uss = schema->schemaTranslate(quant, factor, uus); + + Py::Tuple res(3); + res[0] = Py::String(uss.toUtf8(),"utf-8"); + res[1] = Py::Float(factor); + res[2] = Py::String(uus.toUtf8(),"utf-8"); + + return Py::new_reference_to(res); +} diff --git a/src/Base/UnitsSchema.h b/src/Base/UnitsSchema.h index b894d0f90d..db1c50685e 100644 --- a/src/Base/UnitsSchema.h +++ b/src/Base/UnitsSchema.h @@ -41,8 +41,9 @@ enum UnitSystem { Centimeters = 4, /** All lengths in centimeters, areas and volumes in square/cubic meters */ ImperialBuilding = 5, /** All lengths in feet + inches + fractions */ MmMin = 6, /** Lengths in mm, Speed in mm/min. Angle in degrees. Useful for small parts & CNC */ + NumUnitSystemTypes // must be the last item! }; - + /** The UnitSchema class * The subclasses of this class define the stuff for a