Skip to content

Commit

Permalink
Base: misc patches
Browse files Browse the repository at this point in the history
Convenience macros/function (in Interpreter.h)

* FC_PY_GetObject/Callable(), look for callables in a python object,
  which will be used in future patch to improve performance in various
  python observer/features.

* pyCall(WithKeywords)(), helper function to invoke the callable

Matrix4D:

* hasScale(), check if there is any scale in the transformation. If so,
  further check if the scale is uniform or not. This will be used in
  future patch for Part::TopoShape to decide which type of transform to
  apply.

Placement:

* translate/rotate(), new convenience API

Rotation:

* isSame/multiVec(), new convenience API

Polygon2d:

* Intersect(), GetCenter(), new convenience API.

FlagToggler:

* New class for exception safe flag toggling, similar to StateLocker
  but with template (actually, FlagToggler is added earlier by me).

BitsetLocker:

* New class for exception manipulation of a std::bitset variable.
  • Loading branch information
realthunder committed Jul 14, 2019
1 parent e988af8 commit ff72f02
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 2 deletions.
48 changes: 48 additions & 0 deletions src/Base/Interpreter.h
Expand Up @@ -53,6 +53,40 @@

#include "Exception.h"

/** Helper macro to obtain callable from an object
*
* @param _pyobj: PyObject pointer
* @param _name: the callable string name
* @param _var: the callable variable to be assigned
*
* See FeaturePythonImp::init() for example usage
*/
#define FC_PY_GetCallable(_pyobj,_name,_var) \
do {\
_var = Py::Object();\
if(PyObject_HasAttrString(_pyobj, _name)) {\
Py::Object _obj(PyObject_GetAttrString (_pyobj, _name), true);\
if(_obj.isCallable())\
_var = _obj;\
}\
}while(0)

/** Helper macro to obtain attribute from an object
*
* @param _pyobj: PyObject pointer
* @param _name: the attribute string name
* @param _var: the attribute variable to be assigned
*
* See FeaturePythonImp::init() for example usage
*/
#define FC_PY_GetObject(_pyobj,_name,_var) \
do {\
_var = Py::Object();\
if(PyObject_HasAttrString(_pyobj, _name))\
_var = Py::asObject(PyObject_GetAttrString (_pyobj, _name));\
}while(0)


namespace Base {

using std::string;
Expand Down Expand Up @@ -87,6 +121,20 @@ class BaseExport PyException : public Exception
PyObject *_exceptionType;
};

inline Py::Object pyCall(PyObject *callable, PyObject *args=0) {
PyObject *result = PyObject_CallObject(callable, args);
if(!result)
Base::PyException::ThrowException();
return Py::asObject(result);
}

inline Py::Object pyCallWithKeywords(PyObject *callable, PyObject *args, PyObject *kwds=0) {
PyObject *result = PyObject_Call(callable, args, kwds);
if(!result)
Base::PyException::ThrowException();
return Py::asObject(result);
}

/**
* The SystemExitException is thrown if the Python-internal PyExc_SystemExit exception
* was thrown.
Expand Down
23 changes: 23 additions & 0 deletions src/Base/Matrix.cpp
Expand Up @@ -947,3 +947,26 @@ Matrix4D& Matrix4D::Hat(const Vector3d& rV)

return *this;
}

int Matrix4D::hasScale(double tol) const {
// check for uniform scaling
//
// scaling factors are the colum vector length. We use square distance and
// ignore the actual scaling signess
//
if(!tol)
tol = 1e-9;
double dx = Vector3d(dMtrx4D[0][0],dMtrx4D[1][0],dMtrx4D[2][0]).Sqr();
double dy = Vector3d(dMtrx4D[0][1],dMtrx4D[1][1],dMtrx4D[2][1]).Sqr();
if(fabs(dx-dy)>tol)
return -1;
else {
double dz = Vector3d(dMtrx4D[0][2],dMtrx4D[1][2],dMtrx4D[2][2]).Sqr();
if(fabs(dy-dz)>tol)
return -1;
}
if(fabs(dx-1.0)>tol)
return 1;
else
return 0;
}
2 changes: 2 additions & 0 deletions src/Base/Matrix.h
Expand Up @@ -136,6 +136,8 @@ class BaseExport Matrix4D
/// scale for the x,y,z value
void scale (const Vector3f& rclVct);
void scale (const Vector3d& rclVct);
/// Check for scaling factor, 0: not scale, 1: uniform scale, or else -1
int hasScale(double tol=0.0) const;
/// Rotate around the X axis (in transformed space) for the given value in radians
void rotX (double fAngle);
/// Rotate around the Y axis (in transformed space) for the given value in radians
Expand Down
8 changes: 8 additions & 0 deletions src/Base/MatrixPy.xml
Expand Up @@ -34,6 +34,14 @@ Scale the matrix with the vector
</UserDocu>
</Documentation>
</Methode>
<Methode Name="hasScale">
<Documentation>
<UserDocu>
hasScale(tol=None)
Return 0 is no scale factor, 1 for uniform scaling, -1 for non-uniform scaling.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="unity">
<Documentation>
<UserDocu>unity() - make this matrix to unity</UserDocu>
Expand Down
8 changes: 8 additions & 0 deletions src/Base/MatrixPyImp.cpp
Expand Up @@ -238,6 +238,14 @@ PyObject* MatrixPy::scale(PyObject * args)
Py_Return;
}

PyObject* MatrixPy::hasScale(PyObject * args)
{
double tol=0;
if(!PyArg_ParseTuple(args, "|d", &tol))
return 0;
return Py::new_reference_to(Py::Int(getMatrixPtr()->hasScale(tol)));
}

PyObject* MatrixPy::unity(PyObject * args)
{
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
Expand Down
16 changes: 16 additions & 0 deletions src/Base/PlacementPy.xml
Expand Up @@ -44,6 +44,22 @@ Placement(Base, Axis, Angle) -- define position and rotation
</UserDocu>
</Documentation>
</Methode>
<Methode Name="translate">
<Documentation>
<UserDocu>
translate(Vector)
alias to move(), to be compatible with TopoShape.translate()
</UserDocu>
</Documentation>
</Methode>
<Methode Name="rotate">
<Documentation>
<UserDocu>
rotate(center,axis,degree) - rotate the current placement around center and axis with degree
This method is compatible with TopoShape.rotate()
</UserDocu>
</Documentation>
</Methode>
<Methode Name="multiply" Const="true">
<Documentation>
<UserDocu>
Expand Down
29 changes: 29 additions & 0 deletions src/Base/PlacementPyImp.cpp
Expand Up @@ -33,6 +33,7 @@
#include "MatrixPy.h"
#include "RotationPy.h"
#include "VectorPy.h"
#include "Tools.h"

using namespace Base;

Expand Down Expand Up @@ -158,6 +159,34 @@ PyObject* PlacementPy::move(PyObject * args)
Py_Return;
}

PyObject* PlacementPy::translate(PyObject * args)
{
return move(args);
}

PyObject* PlacementPy::rotate(PyObject *args) {
PyObject *obj1, *obj2;
double angle;
if (!PyArg_ParseTuple(args, "OOd", &obj1, &obj2, &angle))
return NULL;

try {
Py::Sequence p1(obj1), p2(obj2);
Vector3d center((double)Py::Float(p1[0]),
(double)Py::Float(p1[1]),
(double)Py::Float(p1[2]));
Vector3d axis((double)Py::Float(p2[0]),
(double)Py::Float(p2[1]),
(double)Py::Float(p2[2]));
(*getPlacementPtr()) *= Placement(
Vector3d(),Rotation(axis,toRadians<double>(angle)),center);
Py_Return;
}
catch (const Py::Exception&) {
return NULL;
}
}

PyObject* PlacementPy::multiply(PyObject * args)
{
PyObject *plm;
Expand Down
12 changes: 12 additions & 0 deletions src/Base/Rotation.cpp
Expand Up @@ -396,6 +396,18 @@ bool Rotation::isSame(const Rotation& q) const
return false;
}

bool Rotation::isSame(const Rotation& q, double tol) const
{
Vector3d v(0,0,1);
return std::fabs(multVec(v).GetAngle(q.multVec(v))) < tol;
}

Vector3d Rotation::multVec(const Vector3d & src) const {
Vector3d dst;
multVec(src,dst);
return dst;
}

void Rotation::multVec(const Vector3d & src, Vector3d & dst) const
{
double x = this->quat[0];
Expand Down
2 changes: 2 additions & 0 deletions src/Base/Rotation.h
Expand Up @@ -84,8 +84,10 @@ class BaseExport Rotation
void operator = (const Rotation&);

void multVec(const Vector3d & src, Vector3d & dst) const;
Vector3d multVec(const Vector3d & src) const;
void scaleAngle(const double scaleFactor);
bool isSame(const Rotation&) const;
bool isSame(const Rotation&, double tol) const;
//@}

/** Specialty constructors */
Expand Down
44 changes: 44 additions & 0 deletions src/Base/Tools.h
Expand Up @@ -187,6 +187,33 @@ class BaseExport StopWatch

// ----------------------------------------------------------------------------

template<typename Flag=bool>
struct FlagToggler {

Flag &flag;
bool toggled;

FlagToggler(Flag &_flag)
:flag(_flag),toggled(true)
{
flag = !flag;
}

FlagToggler(Flag &_flag, Flag check)
:flag(_flag),toggled(check==_flag)
{
if(toggled)
flag = !flag;
}

~FlagToggler() {
if(toggled)
flag = !flag;
}
};

// ----------------------------------------------------------------------------

template<typename Status, class Object>
class ObjectStatusLocker
{
Expand Down Expand Up @@ -217,6 +244,23 @@ class StateLocker

// ----------------------------------------------------------------------------

template<typename T>
class BitsetLocker
{
public:
BitsetLocker(T& flags, std::size_t flag, bool value = true)
: flags(flags), flag(flag)
{ oldValue = flags.test(flag); flags.set(flag,value); }
~BitsetLocker()
{ flags.set(flag,oldValue); }
private:
T &flags;
std::size_t flag;
bool oldValue;
};

// ----------------------------------------------------------------------------

class ConnectionBlocker {
typedef boost::signals2::connection Connection;
typedef boost::signals2::shared_connection_block ConnectionBlock;
Expand Down
31 changes: 31 additions & 0 deletions src/Base/Tools2D.cpp
Expand Up @@ -431,6 +431,37 @@ void Polygon2d::Intersect (const Polygon2d &rclPolygon, std::list<Polygon2d> &rc
rclResultPolygonList.push_back(clResultPolygon);
}

bool Polygon2d::Intersect (const Polygon2d &other) const {
if(other.GetCtVectors()<2 || GetCtVectors() < 2)
return false;

for(auto &v : _aclVct) {
if(other.Contains(v))
return true;
}

if(Contains(other[0]))
return true;

for(size_t j=1; j<other.GetCtVectors(); ++j) {
auto &v0 = other[j-1];
auto &v1 = other[j];

if(Contains(v1))
return true;

Line2d line(v0, v1);
for(size_t i=0; i<GetCtVectors(); ++i) {
Line2d line2(At(i), At((i+1)%GetCtVectors()));
Vector2d v;
if(line.IntersectAndContain(line2, v))
return true;
}
}
return false;
}


bool Polygon2d::Intersect (const Vector2d &rclV, double eps) const
{
if (_aclVct.size() < 2)
Expand Down
9 changes: 7 additions & 2 deletions src/Base/Tools2D.h
Expand Up @@ -89,7 +89,7 @@ class BaseExport BoundBox2d
inline BoundBox2d (double fX1, double fY1, double fX2, double fY2);
inline bool IsValid (void);
inline bool IsEqual(const BoundBox2d&, double tolerance) const;

// operators
inline BoundBox2d& operator= (const BoundBox2d& rclBB);
inline bool operator== (const BoundBox2d& rclBB) const;
Expand All @@ -102,6 +102,11 @@ class BaseExport BoundBox2d

// misc
bool Contains (const Vector2d &rclV) const;

inline Vector2d GetCenter() const {
return Vector2d((MinX+MaxX)/2,(MinY+MaxY)/2);
}

};

/** Line2d ********************************************/
Expand Down Expand Up @@ -160,6 +165,7 @@ class BaseExport Polygon2d
BoundBox2d CalcBoundBox (void) const;
bool Contains (const Vector2d &rclV) const;
void Intersect (const Polygon2d &rclPolygon, std::list<Polygon2d> &rclResultPolygonList) const;
bool Intersect (const Polygon2d &rclPolygon) const;
bool Intersect (const Vector2d &rclV, double eps) const;

private:
Expand Down Expand Up @@ -308,7 +314,6 @@ inline Vector2d& Polygon2d::At (size_t ulNdx) const
return (Vector2d&) _aclVct[ulNdx];
}


inline Line2d::Line2d (const Line2d &rclLine)
: clV1 (rclLine.clV1),
clV2 (rclLine.clV2)
Expand Down

0 comments on commit ff72f02

Please sign in to comment.