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)