Skip to content

Commit

Permalink
some fixes and comparison interface for Unit and Quantity python objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jriegel committed Dec 5, 2013
1 parent 01d6907 commit 272e606
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 53 deletions.
33 changes: 27 additions & 6 deletions src/App/FreeCADInit.py
Expand Up @@ -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 *
#* *
Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -208,6 +208,27 @@ def InitApplications():
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
Expand Down
8 changes: 8 additions & 0 deletions src/Base/Quantity.cpp
Expand Up @@ -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
{
Expand Down
1 change: 1 addition & 0 deletions src/Base/Quantity.h
Expand Up @@ -57,6 +57,7 @@ class BaseExport Quantity
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;
//@}
Expand Down
1 change: 1 addition & 0 deletions src/Base/QuantityPy.xml
Expand Up @@ -9,6 +9,7 @@
FatherInclude="Base/PyObjectBase.h"
Namespace="Base"
NumberProtocol="true"
RichCompare="true"
Constructor="true"
Delete="true"
FatherNamespace="Base">
Expand Down
52 changes: 52 additions & 0 deletions src/Base/QuantityPyImp.cpp
Expand Up @@ -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)) {

Expand Down Expand Up @@ -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
{
Expand Down
26 changes: 25 additions & 1 deletion src/Base/Unit.cpp
Expand Up @@ -73,7 +73,6 @@ Unit::Unit(const std::string& Pars)

}


Unit Unit::pow(char exp)const
{
Unit result;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
12 changes: 10 additions & 2 deletions src/Base/Unit.h
Expand Up @@ -70,10 +70,13 @@ class BaseExport Unit
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. */
//@{
Expand All @@ -97,6 +100,11 @@ class BaseExport Unit

static Unit Stress;
static Unit Pressure;
static Unit Force;
static Unit Work;
static Unit Power;


//@}
protected:
UnitSignature Sig;
Expand Down
39 changes: 14 additions & 25 deletions src/Base/UnitPy.xml
Expand Up @@ -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>

0 comments on commit 272e606

Please sign in to comment.