Base: misc patches
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.
This commit is contained in:
@@ -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;
|
||||
@@ -87,6 +121,20 @@ protected:
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -136,6 +136,8 @@ public:
|
||||
/// 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "MatrixPy.h"
|
||||
#include "RotationPy.h"
|
||||
#include "VectorPy.h"
|
||||
#include "Tools.h"
|
||||
|
||||
using namespace Base;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -84,8 +84,10 @@ public:
|
||||
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 */
|
||||
|
||||
@@ -187,6 +187,33 @@ private:
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
{
|
||||
@@ -217,6 +244,23 @@ private:
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
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;
|
||||
@@ -102,6 +102,11 @@ public:
|
||||
|
||||
// misc
|
||||
bool Contains (const Vector2d &rclV) const;
|
||||
|
||||
inline Vector2d GetCenter() const {
|
||||
return Vector2d((MinX+MaxX)/2,(MinY+MaxY)/2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Line2d ********************************************/
|
||||
@@ -160,6 +165,7 @@ public:
|
||||
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:
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user