diff --git a/src/App/FreeCADInit.py b/src/App/FreeCADInit.py index 708db37a4..45b20223e 100644 --- a/src/App/FreeCADInit.py +++ b/src/App/FreeCADInit.py @@ -10,19 +10,19 @@ #* * #* This file is part of the FreeCAD CAx development system. * #* * -#* This program is free software; you can redistribute it and/or modify * +#* This program is free software you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * +#* as published by the Free Software Foundation either version 2 of * #* the License, or (at your option) any later version. * #* for detail see the LICENCE text file. * #* * #* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* but WITHOUT ANY WARRANTY without even the implied warranty of * #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * #* GNU Lesser General Public License for more details. * #* * #* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * +#* License along with FreeCAD if not, write to the Free Software * #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * #* USA * #* * @@ -47,7 +47,7 @@ def InitApplications(): BinDir = os.path.realpath(BinDir) LibDir = FreeCAD.getHomePath()+'lib' LibDir = os.path.realpath(LibDir) - AddPath = FreeCAD.ConfigGet("AdditionalModulePaths").split(";") + AddPath = FreeCAD.ConfigGet("AdditionalModulePaths").split(" ") HomeMod = FreeCAD.ConfigGet("UserAppData")+"Mod" HomeMod = os.path.realpath(HomeMod) MacroDir = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro").GetString("MacroPath") @@ -118,7 +118,7 @@ def InitApplications(): if len(platform.mac_ver()[0]) > 0: sys.path.append(os.path.expanduser('~/Library/Application Support/FreeCAD/Mod')) -# some often used shortcuts (for lazy people like me ;-) +# some often used shortcuts (for lazy people like me -) App = FreeCAD Log = FreeCAD.Console.PrintLog Msg = FreeCAD.Console.PrintMessage @@ -208,6 +208,27 @@ App.Units.Degree = App.Units.Quantity('deg') App.Units.Radian = App.Units.Quantity('rad') App.Units.Gon = App.Units.Quantity('gon') +App.Units.Length = App.Units.Unit(1) +App.Units.Area = App.Units.Unit(2) +App.Units.Volume = App.Units.Unit(3) +App.Units.Mass = App.Units.Unit(0,1) +App.Units.Angle = App.Units.Unit(0,0,0,0,0,0,0,1) + +App.Units.TimeSpan = App.Units.Unit(0,0,1) +App.Units.Velocity = App.Units.Unit(1,0,-1) +App.Units.Acceleration = App.Units.Unit(1,0,-2) +App.Units.Temperature = App.Units.Unit(0,0,0,0,1) + +App.Units.ElectricCurrent = App.Units.Unit(0,0,0,1) +App.Units.AmountOfSubstance = App.Units.Unit(0,0,0,0,0,1) +App.Units.LuminoseIntensity = App.Units.Unit(0,0,0,0,0,0,1) + +App.Units.Stress = App.Units.Unit(-1,1,-2) +App.Units.Pressure = App.Units.Unit(-1,1,-2) + +App.Units.Force = App.Units.Unit(1,1,-2) +App.Units.Work = App.Units.Unit(2,1,-2) +App.Units.Power = App.Units.Unit(2,1,-3) # clean up namespace diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index 412507a2e..42f85be38 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -71,6 +71,14 @@ bool Quantity::operator ==(const Quantity& that) const return (this->_Value == that._Value) && (this->_Unit == that._Unit) ; } +bool Quantity::operator <(const Quantity& that) const +{ + if(this->_Unit != that._Unit) + throw Base::Exception("Quantity::operator <(): quantities need to have same unit to compare"); + + return (this->_Value < that._Value) ; +} + Quantity Quantity::operator *(const Quantity &p) const { diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h index 4dbfd93bd..fa7b8e3b5 100644 --- a/src/Base/Quantity.h +++ b/src/Base/Quantity.h @@ -57,6 +57,7 @@ public: Quantity operator -(void) const; Quantity operator /(const Quantity &p) const; bool operator ==(const Quantity&) const; + bool operator < (const Quantity&) const; Quantity& operator =(const Quantity&); Quantity pow(const Quantity&)const; //@} diff --git a/src/Base/QuantityPy.xml b/src/Base/QuantityPy.xml index 51a6a75fc..81a253162 100644 --- a/src/Base/QuantityPy.xml +++ b/src/Base/QuantityPy.xml @@ -9,6 +9,7 @@ FatherInclude="Base/PyObjectBase.h" Namespace="Base" NumberProtocol="true" + RichCompare="true" Constructor="true" Delete="true" FatherNamespace="Base"> diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index e3c6085a0..f0bd08257 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -56,6 +56,12 @@ int QuantityPy::PyInit(PyObject* args, PyObject* kwd) return 0; } PyErr_Clear(); // set by PyArg_ParseTuple() + if (PyArg_ParseTuple(args,"dO!",&f,&(Base::UnitPy::Type), &object)) { + // Note: must be static_cast, not reinterpret_cast + *self = Quantity(f,*(static_cast(object)->getUnitPtr())); + return 0; + } + PyErr_Clear(); // set by PyArg_ParseTuple() const char* string; if (PyArg_ParseTuple(args,"s", &string)) { @@ -178,6 +184,52 @@ PyObject* QuantityPy::number_multiply_handler(PyObject *self, PyObject *other) } } +PyObject* QuantityPy::richCompare(PyObject *v, PyObject *w, int op) +{ + if (PyObject_TypeCheck(v, &(QuantityPy::Type)) && + PyObject_TypeCheck(w, &(QuantityPy::Type))) { + const Quantity * u1 = static_cast(v)->getQuantityPtr(); + const Quantity * u2 = static_cast(w)->getQuantityPtr(); + + PyObject *res=0; + if (op == Py_NE) { + res = (!(*u1 == *u2)) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else if (op == Py_LT) { + res = (*u1 < *u2) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else if (op == Py_LE) { + res = (*u1 < *u2)||(*u1 == *u2) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else if (op == Py_GT) { + res = (!(*u1 < *u2))&&(!(*u1 == *u2)) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else if (op == Py_GE) { + res = (!(*u1 < *u2)) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else if (op == Py_EQ) { + res = (*u1 == *u2) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + + } + + // This always returns False + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + +} Py::Float QuantityPy::getValue(void) const { diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index 4db9862ee..b560b74d8 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -73,7 +73,6 @@ Unit::Unit(const std::string& Pars) } - Unit Unit::pow(char exp)const { Unit result; @@ -316,6 +315,27 @@ std::string Unit::getString(void) const return ret.str(); } +std::string Unit::getTypeString(void) const +{ + if(*this == Unit::Length ) return "Length"; else + if(*this == Unit::Area ) return "Area"; else + if(*this == Unit::Volume ) return "Volume"; else + if(*this == Unit::Mass ) return "Mass"; else + if(*this == Unit::Angle ) return "Angle"; else + if(*this == Unit::TimeSpan ) return "TimeSpan"; else + if(*this == Unit::Velocity ) return "Velocity"; else + if(*this == Unit::Acceleration ) return "Acceleration"; else + if(*this == Unit::Temperature ) return "Temperature"; else + if(*this == Unit::ElectricCurrent ) return "ElectricCurrent"; else + if(*this == Unit::AmountOfSubstance ) return "AmountOfSubstance"; else + if(*this == Unit::LuminoseIntensity ) return "LuminoseIntensity"; else + if(*this == Unit::Pressure ) return "Pressure"; else + if(*this == Unit::Force ) return "Force"; else + if(*this == Unit::Work ) return "Work"; else + if(*this == Unit::Power ) return "Power"; else + return ""; + +} Unit Unit::Length(1); Unit Unit::Area(2); @@ -334,3 +354,7 @@ 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 + +Unit Unit::Force (1,1,-2); +Unit Unit::Work (2,1,-2); +Unit Unit::Power (2,1,-3); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 5e7368150..cb30d1ee2 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -70,10 +70,13 @@ public: Unit& operator =(const Unit&); Unit pow(char exp)const; //@} - + /// get the unit signature + const UnitSignature & getSignature(void)const {return Sig;} bool isEmpty(void)const; - char getLengthDimension(void){return Sig.Length;} + std::string getString(void) const; + /// get the type as an string such as "Area", "Length" or "Pressure". + std::string getTypeString(void) const; /** Predefined Unit types. */ //@{ @@ -97,6 +100,11 @@ public: static Unit Stress; static Unit Pressure; + static Unit Force; + static Unit Work; + static Unit Power; + + //@} protected: UnitSignature Sig; diff --git a/src/Base/UnitPy.xml b/src/Base/UnitPy.xml index 60ad8e41b..47e8dcf7e 100644 --- a/src/Base/UnitPy.xml +++ b/src/Base/UnitPy.xml @@ -9,41 +9,30 @@ FatherInclude="Base/PyObjectBase.h" Namespace="Base" NumberProtocol="true" + RichCompare="true" Constructor="true" Delete="true" FatherNamespace="Base"> - Unit -defines a unit type and calculate and compare. + + Unit + defines a unit type, calculate and compare. -The following constructors are supported: -Unit() -- empty constructor -Unit(Unit) -- copy constructor -Unit(string) -- parse the string for units - + The following constructors are supported: + Unit() -- empty constructor + Unit(i1,i2,i3,i4,i5,i6,i7,i8) -- unit signature + Unit(Quantity) -- copy unit from Quantity + Unit(Unit) -- copy constructor + Unit(string) -- parse the string for units + Unit - + - - multiply(Placement) - Multiply this axis with a placement - + holds the unit type as a string, e.g. 'Area'. - - - - - get the type of the unit as string - - - - - - get the dimension as a vector with 8 fields - - + diff --git a/src/Base/UnitPyImp.cpp b/src/Base/UnitPyImp.cpp index 52b40b6b4..ff3b6d7d1 100644 --- a/src/Base/UnitPyImp.cpp +++ b/src/Base/UnitPyImp.cpp @@ -5,6 +5,7 @@ // inclusion of the generated files (generated out of UnitPy.xml) #include "UnitPy.h" +#include "QuantityPy.h" #include "UnitPy.cpp" using namespace Base; @@ -12,7 +13,23 @@ using namespace Base; // returns a string which represents the object e.g. when printed in python std::string UnitPy::representation(void) const { - return std::string(""); + const UnitSignature & Sig = getUnitPtr()->getSignature(); + std::stringstream ret; + ret << "Unit: "; + ret << getUnitPtr()->getString() << " ("; + ret << Sig.Length << ","; + ret << Sig.Mass << ","; + ret << Sig.Time << ","; + ret << Sig.ElectricCurrent << ","; + ret << Sig.ThermodynamicTemperature << ","; + ret << Sig.AmountOfSubstance << ","; + ret << Sig.LuminoseIntensity << ","; + ret << Sig.Angle << ")"; + std::string type = getUnitPtr()->getTypeString(); + if(! type.empty()) + ret << " [" << type << "]"; + + return ret.str(); } PyObject *UnitPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper @@ -22,22 +39,48 @@ PyObject *UnitPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Pytho } // constructor method -int UnitPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +int UnitPy::PyInit(PyObject* args, PyObject* kwd) { - return 0; -} + Unit *self = getUnitPtr(); + int i1=0; + int i2=0; + int i3=0; + int i4=0; + int i5=0; + int i6=0; + int i7=0; + int i8=0; + if (PyArg_ParseTuple(args, "|iiiiiiii", &i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8)) { + *self = Unit(i1,i2,i3,i4,i5,i6,i7,i8); + return 0; + } + PyErr_Clear(); // set by PyArg_ParseTuple() -PyObject* UnitPy::multiply(PyObject * /*args*/) -{ - PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); - return 0; -} + PyObject *object; -PyObject* UnitPy::getType(PyObject * /*args*/) -{ - PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); - return 0; + if (PyArg_ParseTuple(args,"O!",&(Base::QuantityPy::Type), &object)) { + // Note: must be static_cast, not reinterpret_cast + *self = static_cast(object)->getQuantityPtr()->getUnit(); + return 0; + } + PyErr_Clear(); // set by PyArg_ParseTuple() + + if (PyArg_ParseTuple(args,"O!",&(Base::UnitPy::Type), &object)) { + // Note: must be static_cast, not reinterpret_cast + *self = *(static_cast(object)->getUnitPtr()); + return 0; + } + PyErr_Clear(); // set by PyArg_ParseTuple() + const char* string; + if (PyArg_ParseTuple(args,"s", &string)) { + + *self = Quantity::parse(string).getUnit(); + return 0; + } + + PyErr_SetString(PyExc_TypeError, "Either string, (float,8 ints), Unit() or Quantity()"); + return -1; } @@ -102,18 +145,44 @@ PyObject* UnitPy::number_multiply_handler(PyObject *self, PyObject *other) } } - -Py::Object UnitPy::getDimensions(void) const +PyObject* UnitPy::richCompare(PyObject *v, PyObject *w, int op) { - //return Py::Object(); - throw Py::AttributeError("Not yet implemented"); + if (PyObject_TypeCheck(v, &(UnitPy::Type)) && + PyObject_TypeCheck(w, &(UnitPy::Type))) { + const Unit * u1 = static_cast(v)->getUnitPtr(); + const Unit * u2 = static_cast(w)->getUnitPtr(); + + PyObject *res=0; + if (op != Py_EQ && op != Py_NE) { + PyErr_SetString(PyExc_TypeError, + "no ordering relation is defined for Units"); + return 0; + } + else if (op == Py_EQ) { + res = (*u1 == *u2) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + else { + res = (*u1 != *u2) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } + } + else { + // This always returns False + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } } -void UnitPy::setDimensions(Py::Object /*arg*/) +Py::String UnitPy::getType(void) const { - throw Py::AttributeError("Not yet implemented"); + return Py::String(getUnitPtr()->getTypeString()); } + + PyObject *UnitPy::getCustomAttributes(const char* /*attr*/) const { return 0;