Implement Matrix3x3 missing members and documentation (More!!!)
All checks were successful
Build Docs With Doxygen / Explore-Gitea-Actions (push) Successful in 1m3s

This commit is contained in:
2024-05-13 12:33:43 -04:00
parent 3e8f83ddfb
commit 6544d0ddbe
2 changed files with 144 additions and 1 deletions

View File

@@ -383,6 +383,8 @@ namespace J3ML::LinearAlgebra {
/// Performs a batch transformation of the given array.
void BatchTransform(Vector3 *pointArray, int numPoints) const;
void BatchTransform(Vector3 *pointArray, int numPoints, int stride) const;
void BatchTransform(Vector4 *vectorArray, int numVectors) const;
void BatchTransform(Vector4 *vectorArray, int numVectors, int stride) const;
/// Returns the sum of the diagonal elements of this matrix.
float Trace() const;
@@ -393,19 +395,32 @@ namespace J3ML::LinearAlgebra {
Vector3 operator[](int row) const;
/// Transforms the given vector by this matrix (in the order M * v).
Vector2 operator * (const Vector2& rhs) const;
Vector3 operator * (const Vector3& rhs) const;
/// Transforms the given vector by this matrix (in the order M * v).
/// This function ignores the W component of the given input vector. This component is assumed to be either 0 or 1.
Vector4 operator * (const Vector4& rhs) const;
/// Multiplies the two matrices.
Matrix3x3 operator * (const Matrix3x3& rhs) const;
Matrix4x4 operator * (const Matrix4x4& rhs) const;
Matrix3x3 Mul(const Matrix3x3& rhs) const;
/// Multiplies the two matrices.
Matrix4x4 operator * (const Matrix4x4& rhs) const;
Matrix4x4 Mul(const Matrix4x4& rhs) const;
Vector2 Mul(const Vector2& rhs) const;
Vector3 Mul(const Vector3& rhs) const;
Vector4 Mul(const Vector4& rhs) const;
/// Converts the quaternion to a M3x3 and multiplies the two matrices together.
Matrix3x3 operator *(const Quaternion& rhs) const;
Quaternion Mul(const Quaternion& rhs) const;
// Returns true if the column vectors of this matrix are all perpendicular to each other.
bool IsColOrthogonal(float epsilon = 1e-3f) const;
bool IsColOrthogonal3(float epsilon = 1e-3f) const { return IsColOrthogonal(epsilon);}
// Returns true if the row vectors of this matrix are all perpendicular to each other.
bool IsRowOrthogonal(float epsilon = 1e-3f) const;
@@ -414,6 +429,51 @@ namespace J3ML::LinearAlgebra {
Vector3 ExtractScale() const;
/// Tests if this matrix does not contain any NaNs or infs
/// @return Returns true if the entries of this M3x3 are all finite.
bool IsFinite() const;
/// Tests if this is the identity matrix.
/// @return Returns true if this matrix is the identity matrix, up to the given epsilon.
bool IsIdentity(float epsilon = 1e-3f) const;
/// Tests if this matrix is in lower triangular form.
/// @return Returns true if this matrix is in lower triangular form, up to the given epsilon.
bool IsLowerTriangular(float epsilon = 1e-3f) const;
/// Tests if this matrix is in upper triangular form.
/// @return Returns true if this matrix is in upper triangular form, up to the given epsilon.
bool IsUpperTriangular(float epsilon = 1e-3f) const;
/// Tests if this matrix has an inverse.
/// @return Returns true if this matrix can be inverted, up to the given epsilon.
bool IsInvertible(float epsilon = 1e-3f) const;
/// Tests if this matrix is symmetric (M == M^T).
/// The test compares the elements for equality. Up to the given epsilon. A matrix is symmetric if it is its own transpose.
bool IsSymmetric(float epsilon = 1e-3f) const;
/// Tests if this matrix is skew-symmetric (M == -M^T).
/// The test compares the elements of this matrix up to the given epsilon. A matrix M is skew-symmetric if the identity M=-M^T holds.
bool IsSkewSymmetric(float epsilon = 1e-3f) const;
/// Returns true if this matrix does not perform any scaling,
/** A matrix does not do any scaling if the column vectors of this matrix are normalized in length,
compared to the given epsilon. Note that this matrix may still perform reflection,
i.e. it has a -1 scale along some axis.
@note This function only examines the upper 3-by-3 part of this matrix.
@note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0,0,0,1] */
bool HasUnitaryScale(float epsilon = 1e-3f) const;
/// Returns true if this matrix performs a reflection along some plane.
/** In 3D space, an even number of reflections corresponds to a rotation about some axis, so a matrix consisting of
an odd number of consecutive mirror operations can only reflect about one axis. A matrix that contains reflection reverses
the handedness of the coordinate system. This function tests if this matrix does perform mirroring.
This occurs if this matrix has a negative determinant.*/
bool HasNegativeScale() const;
/// Returns true if the column and row vectors of this matrix form an orthonormal set.
/// @note In math terms, there does not exist such a thing as an 'orthonormal matrix'. In math terms, a matrix
/// is orthogonal if the column and row vectors are orthogonal *unit* vectors.
/// In terms of this library however, a matrix is orthogonal if its column and row vectors are orthogonal. (no need to be unitary),
/// and a matrix is orthonormal if the column and row vectors are orthonormal.
bool IsOrthonormal(float epsilon = 1e-3f) const;
protected: /// Member values
float elems[3][3];
};

View File

@@ -529,5 +529,88 @@ namespace J3ML::LinearAlgebra {
}
bool Matrix3x3::IsFinite() const {
for (int y = 0; y < Rows; y++)
for (int x = 0; x < Cols; ++x)
if (!std::isfinite(elems[y][x]))
return false;
return true;
}
/** Compares the two values for equality, allowing the given amount of absolute error. */
bool EqualAbs(float a, float b, float epsilon)
{
return std::abs(a-b) < epsilon;
}
bool Matrix3x3::IsIdentity(float epsilon) const
{
for (int y = 0; y < Rows; ++y)
for (int x = 0; x < Cols; ++x)
if (!EqualAbs(elems[y][x], (x == y) ? 1.f : 0.f, epsilon))
return false;
return true;
}
bool Matrix3x3::IsLowerTriangular(float epsilon) const
{
return EqualAbs(elems[0][1], 0.f, epsilon)
&& EqualAbs(elems[0][2], 0.f, epsilon)
&& EqualAbs(elems[1][2], 0.f, epsilon);
}
bool Matrix3x3::IsUpperTriangular(float epsilon) const
{
return EqualAbs(elems[1][0], 0.f, epsilon)
&& EqualAbs(elems[2][0], 0.f, epsilon)
&& EqualAbs(elems[2][1], 0.f, epsilon);
}
bool Matrix3x3::IsInvertible(float epsilon) const
{
float d = Determinant();
bool isSingular = EqualAbs(d, 0.f, epsilon);
//assert(Inverse(epsilon) == isSingular);
return !isSingular;
}
bool Matrix3x3::IsSymmetric(float epsilon) const
{
return EqualAbs(elems[0][1], elems[1][0], epsilon)
&& EqualAbs(elems[0][2], elems[2][0], epsilon)
&& EqualAbs(elems[1][2], elems[2][1], epsilon);
}
bool Matrix3x3::IsSkewSymmetric(float epsilon) const
{
return EqualAbs(elems[0][0], 0.f, epsilon)
&& EqualAbs(elems[1][1], 0.f, epsilon)
&& EqualAbs(elems[2][2], 0.f, epsilon)
&& EqualAbs(elems[0][1], -elems[1][0], epsilon)
&& EqualAbs(elems[0][2], -elems[2][0], epsilon)
&& EqualAbs(elems[1][2], -elems[2][1], epsilon);
}
bool Matrix3x3::HasUnitaryScale(float epsilon) const {
Vector3 scale = ExtractScale();
return scale.Equals(1.f, 1.f, 1.f, epsilon);
}
bool Matrix3x3::HasNegativeScale() const
{
return Determinant() < 0.f;
}
bool Matrix3x3::IsOrthonormal(float epsilon) const
{
///@todo Epsilon magnitudes don't match.
return IsColOrthogonal(epsilon) && Row(0).IsNormalized(epsilon) && Row(1).IsNormalized(epsilon) && Row(2).IsNormalized(epsilon);
}
}