From eab9afbbad56bd16f8706e64a46ff6430704fb92 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 4 Feb 2022 14:35:27 +0100 Subject: [PATCH] Base: support of multiplication of a matrix with a scalar, add functions to check whether it's the unit or null matrix --- src/Base/Matrix.cpp | 30 ++++++++++++ src/Base/Matrix.h | 28 +++++++++++ src/Base/MatrixPy.xml | 17 ++++++- src/Base/MatrixPyImp.cpp | 103 ++++++++++++++++++++++++++------------- 4 files changed, 143 insertions(+), 35 deletions(-) diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp index a2360db085..48944a2f3c 100644 --- a/src/Base/Matrix.cpp +++ b/src/Base/Matrix.cpp @@ -99,6 +99,24 @@ void Matrix4D::setToUnity () dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 1.0; } +bool Matrix4D::isUnity() const +{ + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i == j) { + if (dMtrx4D[i][j] != 1.0) + return false; + } + else { + if (dMtrx4D[i][j] != 0.0) + return false; + } + } + } + + return true; +} + void Matrix4D::nullify() { dMtrx4D[0][0] = 0.0; dMtrx4D[0][1] = 0.0; dMtrx4D[0][2] = 0.0; dMtrx4D[0][3] = 0.0; @@ -107,6 +125,18 @@ void Matrix4D::nullify() dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 0.0; } +bool Matrix4D::isNull() const +{ + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (dMtrx4D[i][j] != 0.0) + return false; + } + } + + return true; +} + double Matrix4D::determinant() const { double fA0 = dMtrx4D[0][0]*dMtrx4D[1][1] - dMtrx4D[0][1]*dMtrx4D[1][0]; diff --git a/src/Base/Matrix.h b/src/Base/Matrix.h index 275ff5e3e7..064843a19e 100644 --- a/src/Base/Matrix.h +++ b/src/Base/Matrix.h @@ -88,6 +88,8 @@ public: inline Vector3d operator * (const Vector3d& rclVct) const; inline void multVec(const Vector3d & src, Vector3d & dst) const; inline void multVec(const Vector3f & src, Vector3f & dst) const; + inline Matrix4D operator * (double) const; + inline Matrix4D& operator *= (double); /// Comparison inline bool operator != (const Matrix4D& rclMtrx) const; /// Comparison @@ -133,8 +135,12 @@ public: //@{ /// Makes unity matrix void setToUnity(); + /// Checks if this is the unit matrix + bool isUnity() const; /// Makes a null matrix void nullify(); + /// Checks if this is the null matrix + bool isNull() const; /// moves the coordinatesystem for the x,y,z value void move (float x, float y, float z) { move(Vector3f(x,y,z)); } @@ -346,6 +352,28 @@ inline void Matrix4D::multVec(const Vector3f & src, Vector3f & dst) const static_cast(z)); } +inline Matrix4D Matrix4D::operator * (double scalar) const +{ + Matrix4D matrix; + for (unsigned short i = 0; i < 4; i++) { + for (unsigned short j = 0; j < 4; j++) { + matrix.dMtrx4D[i][j] = dMtrx4D[i][j] * scalar; + } + } + + return matrix; +} + +inline Matrix4D& Matrix4D::operator *= (double scalar) +{ + for (unsigned short i = 0; i < 4; i++) { + for (unsigned short j = 0; j < 4; j++) { + dMtrx4D[i][j] *= scalar; + } + } + return *this; +} + inline bool Matrix4D::operator== (const Matrix4D& rclMtrx) const { unsigned short iz, is; diff --git a/src/Base/MatrixPy.xml b/src/Base/MatrixPy.xml index e48119d5c6..d6f4cd52cc 100644 --- a/src/Base/MatrixPy.xml +++ b/src/Base/MatrixPy.xml @@ -34,7 +34,7 @@ Scale the matrix with the vector - + hasScale(tol=None) @@ -42,11 +42,26 @@ Return 0 is no scale factor, 1 for uniform scaling, -1 for non-uniform scaling. + + + nullify() - make this the null matrix + + + + + isNull() - check if this is the null matrix + + unity() - make this matrix to unity + + + isUnity() - check if this is the unit matrix + + transform(Vector,Matrix) - return the dot product of the two vectors diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index a1fc338fa1..a00351eb5f 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -186,8 +186,7 @@ PyObject* MatrixPy::number_multiply_handler(PyObject *self, PyObject *other) if (PyNumber_Check(other)) { double v = PyFloat_AsDouble(other); - a.scale(v,v,v); - return new MatrixPy(a); + return new MatrixPy(a * v); } } @@ -210,14 +209,14 @@ PyObject * MatrixPy::number_power_handler (PyObject* self, PyObject* other, PyOb Base::Matrix4D a = static_cast(self)->value(); long b = Py::Int(other); - if (!b) + if (b == 0) return new MatrixPy(Matrix4D()); if (b < 0) { if (fabs(a.determinant()) > DBL_EPSILON) a.inverseGauss(); else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Cannot invert singular matrix"); + PyErr_SetString(PyExc_RuntimeError, "Cannot invert singular matrix"); return nullptr; } b = -b; @@ -266,7 +265,7 @@ PyObject* MatrixPy::move(PyObject * args) Base::Vector3d vec; PyObject *pcVecObj; - if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { // convert args: Python->C + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { vec.x = x; vec.y = y; vec.z = z; @@ -302,7 +301,7 @@ PyObject* MatrixPy::scale(PyObject * args) Base::Vector3d vec; PyObject *pcVecObj; - if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { // convert args: Python->C + if (PyArg_ParseTuple(args, "ddd", &x,&y,&z)) { vec.x = x; vec.y = y; vec.z = z; @@ -340,10 +339,32 @@ PyObject* MatrixPy::hasScale(PyObject * args) return Py::new_reference_to(Py::Int(getMatrixPtr()->hasScale(tol))); } +PyObject* MatrixPy::nullify(PyObject * args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + PY_TRY { + getMatrixPtr()->nullify(); + Py_Return; + } + PY_CATCH; +} + +PyObject* MatrixPy::isNull(PyObject * args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + PY_TRY { + bool ok = getMatrixPtr()->isNull(); + return Py::new_reference_to(Py::Boolean(ok)); + } + PY_CATCH; +} + PyObject* MatrixPy::unity(PyObject * args) { - if (!PyArg_ParseTuple(args, "")) // convert args: Python->C - return nullptr; // NULL triggers exception + if (!PyArg_ParseTuple(args, "")) + return nullptr; PY_TRY { getMatrixPtr()->setToUnity(); } @@ -352,29 +373,33 @@ PyObject* MatrixPy::unity(PyObject * args) Py_Return; } +PyObject* MatrixPy::isUnity(PyObject * args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + PY_TRY { + bool ok = getMatrixPtr()->isUnity(); + return Py::new_reference_to(Py::Boolean(ok)); + } + PY_CATCH; +} + PyObject* MatrixPy::transform(PyObject * args) { Base::Vector3d vec; Matrix4D mat; PyObject *pcVecObj,*pcMatObj; - if (PyArg_ParseTuple(args, "O!O!: a transform point (Vector) and a transform matrix (Matrix) is needed", - &(Base::VectorPy::Type), &pcVecObj, &(MatrixPy::Type), &pcMatObj) ) { // convert args: Python->C - Base::VectorPy *pcObject = static_cast(pcVecObj); - Base::Vector3d* val = pcObject->getVectorPtr(); - vec.Set(val->x,val->y,val->z); - mat = *(static_cast(pcMatObj)->getMatrixPtr()); - // clears the error from the first PyArg_ParseTuple()6 - PyErr_Clear(); - } - else - return nullptr; // NULL triggers exception + if (!PyArg_ParseTuple(args, "O!O!: a transform point (Vector) and a transform matrix (Matrix) is needed", + &(Base::VectorPy::Type), &pcVecObj, &(MatrixPy::Type), &pcMatObj)) + return nullptr; - PY_TRY { - getMatrixPtr()->transform(vec,mat); - } - PY_CATCH; + Base::VectorPy *pcObject = static_cast(pcVecObj); + Base::Vector3d* val = pcObject->getVectorPtr(); + vec.Set(val->x,val->y,val->z); + mat = *(static_cast(pcMatObj)->getMatrixPtr()); + getMatrixPtr()->transform(vec,mat); Py_Return; } @@ -388,7 +413,7 @@ PyObject* MatrixPy::col(PyObject * args) return Py::new_reference_to(Py::Vector(v)); } - PyErr_SetString(Base::BaseExceptionFreeCADError, "int expected"); + PyErr_SetString(PyExc_TypeError, "int expected"); return nullptr; } @@ -404,7 +429,7 @@ PyObject* MatrixPy::setCol(PyObject * args) Py_Return; } - PyErr_SetString(Base::BaseExceptionFreeCADError, "int and Vector expected"); + PyErr_SetString(PyExc_TypeError, "int and Vector expected"); return nullptr; } @@ -418,7 +443,7 @@ PyObject* MatrixPy::row(PyObject * args) return Py::new_reference_to(Py::Vector(v)); } - PyErr_SetString(Base::BaseExceptionFreeCADError, "int expected"); + PyErr_SetString(PyExc_TypeError, "int expected"); return nullptr; } @@ -434,7 +459,7 @@ PyObject* MatrixPy::setRow(PyObject * args) Py_Return; } - PyErr_SetString(Base::BaseExceptionFreeCADError, "int and Vector expected"); + PyErr_SetString(PyExc_TypeError, "int and Vector expected"); return nullptr; } @@ -459,7 +484,7 @@ PyObject* MatrixPy::setTrace(PyObject * args) Py_Return; } - PyErr_SetString(Base::BaseExceptionFreeCADError, "Vector expected"); + PyErr_SetString(PyExc_TypeError, "Vector expected"); return nullptr; } @@ -963,16 +988,26 @@ PyObject * MatrixPy::number_divmod_handler (PyObject* /*self*/, PyObject* /*othe return nullptr; } -PyObject * MatrixPy::number_negative_handler (PyObject* /*self*/) +PyObject * MatrixPy::number_negative_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); - return nullptr; + if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) { + PyErr_SetString(PyExc_TypeError, "arg must be Matrix"); + return nullptr; + } + + Base::Matrix4D a = static_cast(self)->value(); + return new MatrixPy(a * -1); } -PyObject * MatrixPy::number_positive_handler (PyObject* /*self*/) +PyObject * MatrixPy::number_positive_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); - return nullptr; + if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) { + PyErr_SetString(PyExc_TypeError, "arg must be Matrix"); + return nullptr; + } + + Base::Matrix4D a = static_cast(self)->value(); + return new MatrixPy(a); } PyObject * MatrixPy::number_absolute_handler (PyObject* /*self*/)