Base: support of multiplication of a matrix with a scalar, add functions to check whether it's the unit or null matrix

This commit is contained in:
wmayer
2022-02-04 14:35:27 +01:00
parent aedb961676
commit eab9afbbad
4 changed files with 143 additions and 35 deletions

View File

@@ -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];

View File

@@ -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<float>(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;

View File

@@ -34,7 +34,7 @@ Scale the matrix with the vector
</UserDocu>
</Documentation>
</Methode>
<Methode Name="hasScale">
<Methode Name="hasScale" Const="true">
<Documentation>
<UserDocu>
hasScale(tol=None)
@@ -42,11 +42,26 @@ Return 0 is no scale factor, 1 for uniform scaling, -1 for non-uniform scaling.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="nullify">
<Documentation>
<UserDocu>nullify() - make this the null matrix</UserDocu>
</Documentation>
</Methode>
<Methode Name="isNull" Const="true">
<Documentation>
<UserDocu>isNull() - check if this is the null matrix</UserDocu>
</Documentation>
</Methode>
<Methode Name="unity">
<Documentation>
<UserDocu>unity() - make this matrix to unity</UserDocu>
</Documentation>
</Methode>
<Methode Name="isUnity" Const="true">
<Documentation>
<UserDocu>isUnity() - check if this is the unit matrix</UserDocu>
</Documentation>
</Methode>
<Methode Name="transform">
<Documentation>
<UserDocu>transform(Vector,Matrix) - return the dot product of the two vectors</UserDocu>

View File

@@ -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<MatrixPy*>(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<Base::VectorPy*>(pcVecObj);
Base::Vector3d* val = pcObject->getVectorPtr();
vec.Set(val->x,val->y,val->z);
mat = *(static_cast<MatrixPy*>(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<Base::VectorPy*>(pcVecObj);
Base::Vector3d* val = pcObject->getVectorPtr();
vec.Set(val->x,val->y,val->z);
mat = *(static_cast<MatrixPy*>(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<MatrixPy*>(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<MatrixPy*>(self)->value();
return new MatrixPy(a);
}
PyObject * MatrixPy::number_absolute_handler (PyObject* /*self*/)