some fixes and comparison interface for Unit and Quantity python objects

This commit is contained in:
jriegel 2013-12-06 00:06:40 +01:00
parent 01d69071b6
commit 272e60671b
9 changed files with 226 additions and 53 deletions

View File

@ -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

View File

@ -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
{

View File

@ -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;
//@}

View File

@ -9,6 +9,7 @@
FatherInclude="Base/PyObjectBase.h"
Namespace="Base"
NumberProtocol="true"
RichCompare="true"
Constructor="true"
Delete="true"
FatherNamespace="Base">

View File

@ -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<Base::UnitPy*>(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<QuantityPy*>(v)->getQuantityPtr();
const Quantity * u2 = static_cast<QuantityPy*>(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
{

View File

@ -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);

View File

@ -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;

View File

@ -9,41 +9,30 @@
FatherInclude="Base/PyObjectBase.h"
Namespace="Base"
NumberProtocol="true"
RichCompare="true"
Constructor="true"
Delete="true"
FatherNamespace="Base">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>Unit
defines a unit type and calculate and compare.
<UserDocu>
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
</UserDocu>
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
</UserDocu>
<DeveloperDocu>Unit</DeveloperDocu>
</Documentation>
<Methode Name="multiply">
<Attribute Name="Type" ReadOnly="true">
<Documentation>
<UserDocu>
multiply(Placement)
Multiply this axis with a placement
</UserDocu>
<UserDocu>holds the unit type as a string, e.g. 'Area'.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getType">
<Documentation>
<UserDocu>
get the type of the unit as string
</UserDocu>
</Documentation>
</Methode>
<Attribute Name="Dimensions" ReadOnly="false">
<Documentation>
<UserDocu>get the dimension as a vector with 8 fields</UserDocu>
</Documentation>
<Parameter Name="Direction" Type="Object" />
<Parameter Name="Type" Type="String" />
</Attribute>
</PythonExport>
</GenerateModel>

View File

@ -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("<Unit object>");
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<Base::QuantityPy*>(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<Base::UnitPy*>(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<UnitPy*>(v)->getUnitPtr();
const Unit * u2 = static_cast<UnitPy*>(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;