55#ifndef MATH_SQUAREMATRIX3_HPP
56#define MATH_SQUAREMATRIX3_HPP
70 template<
typename Real>
73 using ElemType = Real;
74 using ElemPoinerType = Real*;
105 if (
this == &m)
return *
this;
120 setupRotMat(eulerAngles[0], eulerAngles[1], eulerAngles[2]);
130 Real sphi, stheta, spsi;
131 Real cphi, ctheta, cpsi;
140 this->data_[0][0] = cpsi * cphi - ctheta * sphi * spsi;
141 this->data_[0][1] = cpsi * sphi + ctheta * cphi * spsi;
142 this->data_[0][2] = spsi * stheta;
144 this->data_[1][0] = -spsi * cphi - ctheta * sphi * cpsi;
145 this->data_[1][1] = -spsi * sphi + ctheta * cphi * cpsi;
146 this->data_[1][2] = cpsi * stheta;
148 this->data_[2][0] = stheta * sphi;
149 this->data_[2][1] = -stheta * cphi;
150 this->data_[2][2] = ctheta;
173 void setupSkewMat(
Vector3<Real> v) { setupSkewMat(v[0], v[1], v[2]); }
175 void setupSkewMat(Real v1, Real v2, Real v3) {
176 this->data_[0][0] = 0;
177 this->data_[0][1] = -v3;
178 this->data_[0][2] = v2;
179 this->data_[1][0] = v3;
180 this->data_[1][1] = 0;
181 this->data_[1][2] = -v1;
182 this->data_[2][0] = -v2;
183 this->data_[2][1] = v1;
184 this->data_[2][2] = 0;
197 this->data_[0][0] = v1;
198 this->data_[1][1] = v2;
199 this->data_[2][2] = v3;
200 this->data_[1][2] = v4;
201 this->data_[2][1] = v4;
202 this->data_[0][2] = v5;
203 this->data_[2][0] = v5;
204 this->data_[0][1] = v6;
205 this->data_[1][0] = v6;
219 this->data_[0][0] = v1;
220 this->data_[1][1] = v2;
221 this->data_[2][2] = v3;
222 this->data_[1][2] = v4;
223 this->data_[0][2] = v5;
224 this->data_[0][1] = v6;
234 RealType ct = cos(angle);
235 RealType st = sin(angle);
238 *
this += st * SquareMatrix3<Real>::setupSkewMat(axis);
251 t = this->data_[0][0] + this->data_[1][1] + this->data_[2][2] + 1.0;
253 if (t > std::numeric_limits<RealType>::epsilon()) {
256 q[1] = (this->data_[1][2] - this->data_[2][1]) * s;
257 q[2] = (this->data_[2][0] - this->data_[0][2]) * s;
258 q[3] = (this->data_[0][1] - this->data_[1][0]) * s;
260 ad1 = this->data_[0][0];
261 ad2 = this->data_[1][1];
262 ad3 = this->data_[2][2];
264 if (ad1 >= ad2 && ad1 >= ad3) {
265 s = 0.5 / sqrt(1.0 + this->data_[0][0] - this->data_[1][1] -
267 q[0] = (this->data_[1][2] - this->data_[2][1]) * s;
269 q[2] = (this->data_[0][1] + this->data_[1][0]) * s;
270 q[3] = (this->data_[0][2] + this->data_[2][0]) * s;
271 }
else if (ad2 >= ad1 && ad2 >= ad3) {
272 s = 0.5 / sqrt(1.0 + this->data_[1][1] - this->data_[0][0] -
274 q[0] = (this->data_[2][0] - this->data_[0][2]) * s;
275 q[1] = (this->data_[0][1] + this->data_[1][0]) * s;
277 q[3] = (this->data_[1][2] + this->data_[2][1]) * s;
279 s = 0.5 / sqrt(1.0 + this->data_[2][2] - this->data_[0][0] -
281 q[0] = (this->data_[0][1] - this->data_[1][0]) * s;
282 q[1] = (this->data_[0][2] + this->data_[2][0]) * s;
283 q[2] = (this->data_[1][2] + this->data_[2][1]) * s;
312 std::min((RealType)1.0, std::max((RealType)-1.0, this->data_[2][2])));
313 ctheta = this->data_[2][2];
314 stheta = sqrt(1.0 - ctheta * ctheta);
326 if (fabs(stheta) < 1e-6) {
328 phi = atan2(-this->data_[1][0], this->data_[0][0]);
332 phi = atan2(this->data_[2][0], -this->data_[2][1]);
333 psi = atan2(this->data_[0][2], this->data_[1][2]);
337 if (phi < 0) phi += 2.0 * Constants::PI;
339 if (psi < 0) psi += 2.0 * Constants::PI;
349 const Real& a,
const Real& b,
350 const Real& epsilon = std::numeric_limits<Real>::epsilon()) {
351 return (epsilon > std::abs(a - b));
354 Vector3<Real> toRPY() {
355 const Real PI = 3.14159265358979323846264;
357 if (closeEnough(this->data_[0][2], -1.0)) {
360 Real z = x + atan2(this->data_[1][0], this->data_[2][0]);
361 return Vector3<Real>(x, y, z);
362 }
else if (closeEnough(this->data_[0][2], 1.0)) {
365 Real z = -x + atan2(-this->data_[1][0], -this->data_[2][0]);
366 return Vector3<Real>(x, y, z);
369 Real x1 = -asin(this->data_[0][2]);
373 atan2(this->data_[1][2] / cos(x1), this->data_[2][2] / cos(x1));
375 atan2(this->data_[1][2] / cos(x2), this->data_[2][2] / cos(x2));
378 atan2(this->data_[0][1] / cos(x1), this->data_[0][0] / cos(x1));
380 atan2(this->data_[0][1] / cos(x2), this->data_[0][0] / cos(x2));
384 if ((std::abs(x1) + std::abs(y1) + std::abs(z1)) <=
385 (std::abs(x2) + std::abs(y2) + std::abs(z2))) {
386 return Vector3<Real>(x1, y1, z1);
388 return Vector3<Real>(x2, y2, z2);
393 Vector<Real, 6> toVoigtTensor() {
394 Vector<Real, 6> voigt;
395 voigt[0] = this->data_[0][0];
396 voigt[1] = this->data_[1][1];
397 voigt[2] = this->data_[2][2];
398 voigt[3] = 0.5 * (this->data_[1][2] + this->data_[2][1]);
399 voigt[4] = 0.5 * (this->data_[0][2] + this->data_[2][0]);
400 voigt[5] = 0.5 * (this->data_[0][1] + this->data_[1][0]);
408 x = this->data_[0][0] * (this->data_[1][1] * this->data_[2][2] -
409 this->data_[1][2] * this->data_[2][1]);
410 y = this->data_[0][1] * (this->data_[1][2] * this->data_[2][0] -
411 this->data_[1][0] * this->data_[2][2]);
412 z = this->data_[0][2] * (this->data_[1][0] * this->data_[2][1] -
413 this->data_[1][1] * this->data_[2][0]);
419 return this->data_[0][0] + this->data_[1][1] + this->data_[2][2];
431 m(0, 0) = this->data_[1][1] * this->data_[2][2] -
432 this->data_[1][2] * this->data_[2][1];
433 m(1, 0) = this->data_[1][2] * this->data_[2][0] -
434 this->data_[1][0] * this->data_[2][2];
435 m(2, 0) = this->data_[1][0] * this->data_[2][1] -
436 this->data_[1][1] * this->data_[2][0];
437 m(0, 1) = this->data_[2][1] * this->data_[0][2] -
438 this->data_[2][2] * this->data_[0][1];
439 m(1, 1) = this->data_[2][2] * this->data_[0][0] -
440 this->data_[2][0] * this->data_[0][2];
441 m(2, 1) = this->data_[2][0] * this->data_[0][1] -
442 this->data_[2][1] * this->data_[0][0];
443 m(0, 2) = this->data_[0][1] * this->data_[1][2] -
444 this->data_[0][2] * this->data_[1][1];
445 m(1, 2) = this->data_[0][2] * this->data_[1][0] -
446 this->data_[0][0] * this->data_[1][2];
447 m(2, 2) = this->data_[0][0] * this->data_[1][1] -
448 this->data_[0][1] * this->data_[1][0];
456 for (
unsigned int i = 0; i < 3; i++)
457 for (
unsigned int j = 0; j < 3; j++)
458 result(j, i) = this->data_[i][j];
492 template<
typename Real>
503 if (w[0] == w[1] && w[0] == w[2]) {
513 for (i = 0; i < 3; i++) {
514 if (w((i + 1) % 3) == w((i + 2) % 3)) {
516 maxVal = fabs(v(i, 0));
518 for (j = 1; j < 3; j++) {
519 if (maxVal < (tmp = fabs(v(i, j)))) {
534 if (v(maxI, maxI) < 0) {
535 v(maxI, 0) = -v(maxI, 0);
536 v(maxI, 1) = -v(maxI, 1);
537 v(maxI, 2) = -v(maxI, 2);
552 v_k =
cross(v_maxI, v_j);
554 v_j =
cross(v_k, v_maxI);
569 maxVal = fabs(v(0, 0));
571 for (i = 1; i < 3; i++) {
572 if (maxVal < (tmp = fabs(v(i, 0)))) {
586 if (fabs(v(1, 1)) < fabs(v(2, 1))) {
594 for (i = 0; i < 2; i++) {
620 template<
typename Real>
625 for (
unsigned int i = 0; i < 3; i++)
626 for (
unsigned int j = 0; j < 3; j++)
627 for (
unsigned int k = 0; k < 3; k++)
628 result(i, j) += m1(i, k) * m2(k, j);
633 template<
typename Real>
634 inline SquareMatrix3<Real> outProduct(
const Vector3<Real>& v1,
635 const Vector3<Real>& v2) {
636 SquareMatrix3<Real> result;
638 for (
unsigned int i = 0; i < 3; i++) {
639 for (
unsigned int j = 0; j < 3; j++) {
640 result(i, j) = v1[i] * v2[j];
650 const Mat3x3d M3Zero(0.0);
Quaternion is a sort of a higher-level complex number.
Real x() const
Returns the value of the first element of this quaternion.
Real z() const
Returns the value of the fourth element of this quaternion.
SquareMatrix< Real, 3 > toRotationMatrix3()
Returns the corresponding rotation matrix (3x3).
Real w() const
Returns the value of the first element of this quaternion.
Real y() const
Returns the value of the thirf element of this quaternion.
Vector< Real, Row > getRow(unsigned int row)
Returns a row of this matrix as a vector.
void setRow(unsigned int row, const Vector< Real, Row > &v)
Sets a row of this matrix.
void swapRow(unsigned int i, unsigned int j)
swap two rows of this matrix
RectMatrix< Real, Row, Col > & operator=(const RectMatrix< Real, Row, Col > &m)
copy assignment operator
static void diagonalize(SquareMatrix3< Real > &a, Vector3< Real > &w, SquareMatrix3< Real > &v)
Extract the eigenvalues and eigenvectors from a 3x3 matrix.
SquareMatrix3(const RectMatrix< Real, 3, 3 > &m)
Construct from a RectMatrix (e.g.
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
SquareMatrix3(Real s)
Constructs and initializes every element of this matrix to a scalar.
Real determinant() const
Returns the determinant of this matrix.
SquareMatrix3()
default constructor
void axisAngle(Vector3d axis, RealType angle)
Uses Rodrigues' rotation formula for a rotation matrix.
void setupRotMat(const Quaternion< Real > &quat)
Sets this matrix to a rotation matrix by quaternion.
SquareMatrix3(Real *array)
Constructs and initializes from an array.
SquareMatrix3< Real > & operator=(const RectMatrix< Real, 3, 3 > &m)
copy assignment operator
Real trace() const
Returns the trace of this matrix.
Quaternion< Real > toQuaternion()
Returns the quaternion from this rotation matrix.
void setupUpperTriangularVoigtTensor(Vector< Real, 6 > vt)
Sets this matrix to an upper-triangular (asymmetric) tensor using Voigt Notation.
void setupRotMat(const Vector3< Real > &eulerAngles)
Sets this matrix to a rotation matrix by three euler angles @ param euler.
SquareMatrix3(const SquareMatrix< Real, 3 > &m)
copy constructor
Vector3< Real > toEulerAngles()
Returns the euler angles from this rotation matrix.
void setupRotMat(Real w, Real x, Real y, Real z)
Sets this matrix to a rotation matrix by quaternion.
void setupRotMat(Real phi, Real theta, Real psi)
Sets this matrix to a rotation matrix by three euler angles.
void setupVoigtTensor(Vector< Real, 6 > vt)
Sets this matrix to a symmetric tensor using Voigt Notation.
static SquareMatrix< Real, Dim > identity()
SquareMatrix< Real, Dim > transpose() const
static int jacobi(SquareMatrix< Real, Dim > &a, Vector< Real, Dim > &d, SquareMatrix< Real, Dim > &v)
void normalize()
Normalizes this vector in place.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).