diff --git a/src/Base/Interpreter.h b/src/Base/Interpreter.h index 64699dd036..13a6875f8c 100644 --- a/src/Base/Interpreter.h +++ b/src/Base/Interpreter.h @@ -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. diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp index f27267dbd7..7748d04204 100644 --- a/src/Base/Matrix.cpp +++ b/src/Base/Matrix.cpp @@ -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; +} diff --git a/src/Base/Matrix.h b/src/Base/Matrix.h index 25fac709ee..d806b1a3dd 100644 --- a/src/Base/Matrix.h +++ b/src/Base/Matrix.h @@ -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 diff --git a/src/Base/MatrixPy.xml b/src/Base/MatrixPy.xml index e377301628..f83d545bce 100644 --- a/src/Base/MatrixPy.xml +++ b/src/Base/MatrixPy.xml @@ -34,6 +34,14 @@ Scale the matrix with the vector + + + +hasScale(tol=None) +Return 0 is no scale factor, 1 for uniform scaling, -1 for non-uniform scaling. + + + unity() - make this matrix to unity diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index 5e617019d1..8ae2b33c0f 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -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 diff --git a/src/Base/PlacementPy.xml b/src/Base/PlacementPy.xml index 943dc87945..2d68208bcd 100644 --- a/src/Base/PlacementPy.xml +++ b/src/Base/PlacementPy.xml @@ -44,6 +44,22 @@ Placement(Base, Axis, Angle) -- define position and rotation + + + + translate(Vector) + alias to move(), to be compatible with TopoShape.translate() + + + + + + + rotate(center,axis,degree) - rotate the current placement around center and axis with degree + This method is compatible with TopoShape.rotate() + + + diff --git a/src/Base/PlacementPyImp.cpp b/src/Base/PlacementPyImp.cpp index cdef3e57e7..61ed21885a 100644 --- a/src/Base/PlacementPyImp.cpp +++ b/src/Base/PlacementPyImp.cpp @@ -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(angle)),center); + Py_Return; + } + catch (const Py::Exception&) { + return NULL; + } +} + PyObject* PlacementPy::multiply(PyObject * args) { PyObject *plm; diff --git a/src/Base/Rotation.cpp b/src/Base/Rotation.cpp index 3fc98d2929..6c378ecf71 100644 --- a/src/Base/Rotation.cpp +++ b/src/Base/Rotation.cpp @@ -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]; diff --git a/src/Base/Rotation.h b/src/Base/Rotation.h index 679d07934d..f334ce2aca 100644 --- a/src/Base/Rotation.h +++ b/src/Base/Rotation.h @@ -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 */ diff --git a/src/Base/Tools.h b/src/Base/Tools.h index 5521715b3c..5c51974aa7 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -187,6 +187,33 @@ private: // ---------------------------------------------------------------------------- +template +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 class ObjectStatusLocker { @@ -217,6 +244,23 @@ private: // ---------------------------------------------------------------------------- +template +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; diff --git a/src/Base/Tools2D.cpp b/src/Base/Tools2D.cpp index 674d14c2aa..1c8659f839 100644 --- a/src/Base/Tools2D.cpp +++ b/src/Base/Tools2D.cpp @@ -431,6 +431,37 @@ void Polygon2d::Intersect (const Polygon2d &rclPolygon, std::list &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 &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)