File indexing completed on 2025-01-05 03:58:40
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2014 Gerhard Holtkamp 0004 // 0005 0006 /*********************************************************************** 0007 3-Dim Vector and Matrix Definitions and Operations 0008 0009 License:GNU LGPL Version 2+ 0010 0011 Author: Gerhard HOLTKAMP 14-JAN-2012 0012 ***********************************************************************/ 0013 0014 //#include <iostream> 0015 #include "attlib.h" 0016 #include <cmath> 0017 using namespace std; 0018 0019 /*********************************************************************/ 0020 double atan20 (double y, double x) 0021 { 0022 /* redefine atan2 so that it doesn't crash when both x and y are 0 */ 0023 double result; 0024 0025 if ((x == 0) && (y == 0)) result = 0; 0026 else result = atan2 (y, x); 0027 0028 return result; 0029 } 0030 0031 0032 Vec3::Vec3(double x, double y, double z) 0033 {assign(x, y, z);} 0034 0035 Vec3::Vec3 (const Vec3& c) 0036 { 0037 for (int j = 0; j<3; j++) v[j] = c.v[j]; 0038 } 0039 0040 0041 void Vec3::assign (double x, double y, double z) 0042 { 0043 v[0]=x; v[1]=y; v[2]=z; 0044 } 0045 0046 double& Vec3::operator [] (unsigned index) 0047 { 0048 return (index < 3) ? * (v + index) : *v; 0049 } 0050 0051 Vec3& Vec3::operator = (const Vec3& c) 0052 { 0053 for (int j = 0; j<3; j++) v[j] = c.v[j]; 0054 return *this; 0055 } 0056 0057 Vec3& Vec3::operator += (const Vec3& c) 0058 { 0059 for (int j = 0; j<3; j++) v[j] = v[j] + c.v[j]; 0060 return *this; 0061 } 0062 0063 Vec3& Vec3::operator -= (const Vec3& c) 0064 { 0065 for (int j = 0; j<3; j++) v[j] = v[j] - c.v[j]; 0066 return *this; 0067 } 0068 0069 Vec3& Vec3::operator *= (const Vec3& c) // cross product 0070 { 0071 Vec3 result; 0072 result.v[0] = v[1] * c.v[2] - v[2] * c.v[1]; 0073 result.v[1] = v[2] * c.v[0] - v[0] * c.v[2]; 0074 result.v[2] = v[0] * c.v[1] - v[1] * c.v[0]; 0075 for (int j = 0; j<3; j++) v[j] = result.v[j]; 0076 return *this; 0077 } 0078 0079 Vec3& Vec3::operator *= (double r) 0080 { 0081 for (int j = 0; j<3; j++) v[j] = r * v[j]; 0082 return *this; 0083 } 0084 0085 Vec3& Vec3::operator /= (double r) 0086 { 0087 double q; 0088 0089 if (r < 1E-100) q = 0.0; 0090 else q = 1.0 / r; 0091 for (int j = 0; j<3; j++) v[j] = q * v[j]; 0092 return *this; 0093 } 0094 0095 double abs(const Vec3& c) // absolute value 0096 { 0097 double result=0; 0098 0099 for (int j=0; j<3; j++) result += c.v[j]*c.v[j]; 0100 return sqrt(result); 0101 } 0102 0103 double dot (const Vec3& c1, const Vec3& c2) // dot product 0104 { 0105 double result=0; 0106 0107 for (int j = 0; j<3; j++) result += c1.v[j]*c2.v[j]; 0108 return result; 0109 } 0110 0111 Vec3 operator + (const Vec3& c1, const Vec3& c2) 0112 { 0113 Vec3 result; 0114 0115 for (int j = 0; j<3; j++) result.v[j] = c1.v[j] + c2.v[j]; 0116 return result; 0117 } 0118 0119 Vec3 operator - (const Vec3& c1, const Vec3& c2) 0120 { 0121 Vec3 result; 0122 0123 for (int j = 0; j<3; j++) result.v[j] = c1.v[j] - c2.v[j]; 0124 0125 return result; 0126 } 0127 0128 Vec3 operator * (double r, const Vec3& c1) 0129 { 0130 Vec3 result; 0131 0132 for (int j = 0; j<3; j++) result.v[j] = r * c1.v[j]; 0133 return result; 0134 } 0135 0136 Vec3 operator * (const Vec3& c1, double r) 0137 { 0138 Vec3 result; 0139 0140 for (int j = 0; j<3; j++) result.v[j] = c1.v[j] * r; 0141 return result; 0142 } 0143 0144 Vec3 operator * (const Vec3& c1, const Vec3& c2) // cross product 0145 { 0146 Vec3 result; 0147 0148 result.v[0] = c1.v[1] * c2.v[2] - c1.v[2] * c2.v[1]; 0149 result.v[1] = c1.v[2] * c2.v[0] - c1.v[0] * c2.v[2]; 0150 result.v[2] = c1.v[0] * c2.v[1] - c1.v[1] * c2.v[0]; 0151 return result; 0152 } 0153 0154 Vec3 operator / (const Vec3& c1, double r) 0155 { 0156 double q; 0157 Vec3 result; 0158 0159 if (r < 1E-100) q = 0.0; 0160 else q = 1.0 / r; 0161 for (int j = 0; j<3; j++) result.v[j] = q * c1.v[j]; 0162 return result; 0163 } 0164 0165 Vec3 vnorm (const Vec3& c) // norm vector 0166 { 0167 int j; 0168 double q=0; 0169 Vec3 result; 0170 0171 for (j=0; j<3; j++) q += c.v[j]*c.v[j]; 0172 q = sqrt(q); 0173 if (q < 1E-100) q = 0.0; 0174 else q = 1.0 / q; 0175 for (j=0; j<3; j++) result.v[j] = c.v[j]*q; 0176 return result; 0177 } 0178 0179 Vec3 carpol (const Vec3& c) // Cartesian -> Polar 0180 /* Convert vector from cartesian coordinates c = [x, y, z] 0181 into polar coordinates v = [rho, phi, theta] 0182 where rho is the radius, phi the "azimuth" and theta the 0183 "declination" (equatorial plane = 0, pole = 90ø) 0184 */ 0185 { 0186 double x, y, z, r; 0187 Vec3 result; 0188 0189 x = c.v[0]; 0190 y = c.v[1]; 0191 z = c.v[2]; 0192 r = x*x + y*y; 0193 result.v[0] = sqrt (r + z*z); 0194 result.v[1] = atan20 (y, x); 0195 if (result.v[1] < 0) result.v[1] += 2.0*M_PI; 0196 r = sqrt (r); 0197 result.v[2] = atan20 (z, r); 0198 0199 return result; 0200 } 0201 0202 Vec3 polcar (const Vec3& c) // Polar -> Cartesian 0203 /* Convert vector from polar coordinates c = [rho, phi, theta] 0204 where rho is the radius, phi the "azimuth" and theta the 0205 "declination" (equatorial plane = 0, pole = 90ø) 0206 into vector v = [x, y, z] of cartesian coordinates. 0207 */ 0208 { 0209 double r; 0210 Vec3 result; 0211 0212 r = c.v[0] * cos(c.v[2]); 0213 result.v[0] = r * cos(c.v[1]); 0214 result.v[1] = r * sin(c.v[1]); 0215 result.v[2] = c.v[0] * sin(c.v[2]); 0216 0217 return result; 0218 } 0219 0220 ostream& operator << (ostream& os, const Vec3& c) 0221 { 0222 os << "[" << c.v[0] << "," << c.v[1] << "," << c.v[2] << "]"; 0223 return os; 0224 } 0225 0226 /*******************************************************************/ 0227 0228 Mat3::Mat3 (double x) 0229 { 0230 int i, j; 0231 0232 for (i=0; i<3; i++) 0233 for (j=0; j<3; j++) m[i][j] = x; 0234 } 0235 0236 Mat3::Mat3 (const Mat3& c) 0237 { 0238 int i, j; 0239 0240 for (i=0; i<3; i++) 0241 for (j=0; j<3; j++) m[i][j] = c.m[i][j]; 0242 } 0243 0244 void Mat3::assign (double x11, double x12, double x13, 0245 double x21, double x22, double x23, 0246 double x31, double x32, double x33) 0247 { 0248 m[0][0] = x11; 0249 m[0][1] = x12; 0250 m[0][2] = x13; 0251 m[1][0] = x21; 0252 m[1][1] = x22; 0253 m[1][2] = x23; 0254 m[2][0] = x31; 0255 m[2][1] = x32; 0256 m[2][2] = x33; 0257 } 0258 0259 void Mat3::assign (double x[3][3]) 0260 { 0261 int i, j; 0262 0263 for (i=0; i<3; i++) 0264 for (j=0; j<3; j++) m[i][j] = x[i][j]; 0265 } 0266 0267 void Mat3::PutMij (double x, int i, int j) 0268 { 0269 if ((i>0) && (i<4) && (j>0) && (j<4)) m[i-1][j-1] = x; 0270 } 0271 0272 double Mat3::GetMij (int i, int j) 0273 { 0274 double result; 0275 0276 if ((i>0) && (i<4) && (j>0) && (j<4)) result = m[i-1][j-1]; 0277 else result = 0; 0278 return result; 0279 } 0280 0281 0282 Mat3& Mat3::operator = (const Mat3& c) 0283 { 0284 int i, j; 0285 0286 for (i=0; i<3; i++) 0287 for (j=0; j<3; j++) m[i][j] = c.m[i][j]; 0288 0289 return (*this); 0290 } 0291 0292 Mat3& Mat3::operator += (const Mat3& c) 0293 { 0294 int i, j; 0295 0296 for (i=0; i<3; i++) 0297 for (j=0; j<3; j++) m[i][j] = m[i][j] + c.m[i][j]; 0298 return *this; 0299 } 0300 0301 Mat3& Mat3::operator -= (const Mat3& c) 0302 { 0303 int i, j; 0304 0305 for (i=0; i<3; i++) 0306 for (j=0; j<3; j++) m[i][j] = m[i][j] - c.m[i][j]; 0307 return *this; 0308 } 0309 0310 Mat3& Mat3::operator *= (const Mat3& c) 0311 { 0312 int i, j, k; 0313 double r; 0314 Mat3 b; 0315 0316 for (i=0; i<3; i++) 0317 for (j=0; j<3; j++) 0318 { 0319 r = 0; 0320 for (k=0; k<3; k++) r = r + c.m[i][k] * m[k][j]; 0321 b.m[i][j] = r; 0322 } 0323 0324 for (i=0; i<3; i++) 0325 for (j=0; j<3; j++) m[i][j] = b.m[i][j]; 0326 0327 return *this; 0328 } 0329 0330 Mat3& Mat3::operator *= (double r) 0331 { 0332 int i, j; 0333 0334 for (i=0; i<3; i++) 0335 for (j=0; j<3; j++) m[i][j] = r*m[i][j]; 0336 return *this; 0337 } 0338 0339 Mat3& Mat3::operator /= (double r) 0340 { 0341 int i, j; 0342 double q; 0343 0344 if (r < 1E-100) q = 0.0; 0345 else q = 1.0 / r; 0346 0347 for (i=0; i<3; i++) 0348 for (j=0; j<3; j++) m[i][j] = m[i][j] * q; 0349 return *this; 0350 } 0351 0352 Mat3 mxcon (double r) // constant matrix with all elements of value r 0353 { 0354 Mat3 result; 0355 int i, j; 0356 0357 for (i=0; i<3; i++) 0358 for (j=0; j<3; j++) result.m[i][j] = r; 0359 0360 return result; 0361 } 0362 0363 Mat3 mxidn () // identity matrix 0364 { 0365 Mat3 result; 0366 int i; 0367 0368 result = mxcon (0); 0369 for (i=0; i<3; i++) result.m[i][i] = 1.0; 0370 0371 return result; 0372 } 0373 0374 Mat3 mxtrn (const Mat3& m1) // returns transposed of matrix m1 0375 { 0376 Mat3 result; 0377 int i, j; 0378 0379 for (i=0; i<3; i++) 0380 for (j=0; j<3; j++) result.m[i][j] = m1.m[j][i]; 0381 0382 return result; 0383 } 0384 0385 double mxdet (const Mat3& c) // returns determinant of matrix m1 0386 { 0387 double result; 0388 0389 result = c.m[0][0]*c.m[1][1]*c.m[2][2] + c.m[0][1]*c.m[1][2]*c.m[2][0] 0390 + c.m[0][2]*c.m[1][0]*c.m[2][1] - c.m[0][2]*c.m[1][1]*c.m[2][0] 0391 - c.m[0][0]*c.m[1][2]*c.m[2][1] - c.m[0][1]*c.m[1][0]*c.m[2][2]; 0392 0393 return result; 0394 } 0395 0396 Mat3 operator + (const Mat3& c1, const Mat3& c2) 0397 { 0398 Mat3 result; 0399 int i, j; 0400 0401 for (i=0; i<3; i++) 0402 for (j=0; j<3; j++) result.m[i][j] = c1.m[i][j] + c2.m[i][j]; 0403 return result; 0404 } 0405 0406 Mat3 operator - (const Mat3& c1, const Mat3& c2) 0407 { 0408 Mat3 result; 0409 int i, j; 0410 0411 for (i=0; i<3; i++) 0412 for (j=0; j<3; j++) result.m[i][j] = c1.m[i][j] - c2.m[i][j]; 0413 return result; 0414 } 0415 0416 Mat3 operator * (double r, const Mat3& c1) 0417 { 0418 Mat3 result; 0419 int i, j; 0420 0421 for (i=0; i<3; i++) 0422 for (j=0; j<3; j++) result.m[i][j] = c1.m[i][j] * r; 0423 return result; 0424 } 0425 0426 0427 Mat3 operator * (const Mat3& c1, double r) 0428 { 0429 int i, j; 0430 Mat3 result; 0431 0432 for (i=0; i<3; i++) 0433 for (j=0; j<3; j++) result.m[i][j] = c1.m[i][j] * r; 0434 return result; 0435 } 0436 0437 Mat3 operator * (const Mat3& c1, const Mat3& c2) 0438 { 0439 int i, j, k; 0440 double r; 0441 Mat3 result; 0442 0443 for (i=0; i<3; i++) 0444 for (j=0; j<3; j++) 0445 { 0446 r = 0; 0447 for (k=0; k<3; k++) r = r + c1.m[i][k] * c2.m[k][j]; 0448 result.m[i][j] = r; 0449 }; 0450 0451 return result; 0452 } 0453 0454 Mat3 operator / (const Mat3& c1, double r) 0455 { 0456 Mat3 result; 0457 int i, j; 0458 double q; 0459 0460 if (r < 1E-100) q = 0.0; 0461 else q = 1.0 / r; 0462 0463 for (i=0; i<3; i++) 0464 for (j=0; j<3; j++) result.m[i][j] = c1.m[i][j] * q; 0465 return result; 0466 } 0467 0468 Vec3 mxvct (const Mat3& m1, Vec3& v1) 0469 { 0470 int i, j; 0471 double r; 0472 Vec3 result; 0473 0474 for (i=0; i<3; i++) 0475 { 0476 r = 0; 0477 for (j=0; j<3; j++) r = r + m1.m[i][j] * v1[j]; 0478 result[i] = r; 0479 }; 0480 return result; 0481 } 0482 0483 Mat3 xrot (double a) 0484 { 0485 // Rotation matrix around x-axis with angle a (in radians). 0486 double c, s; 0487 Mat3 m1; 0488 0489 c = cos (a); 0490 s = sin (a); 0491 m1.m[0][0] = 1.0; 0492 m1.m[0][1] = 0.0; 0493 m1.m[0][2] = 0.0; 0494 m1.m[1][0] = 0.0; 0495 m1.m[1][1] = c; 0496 m1.m[1][2] = s; 0497 m1.m[2][0] = 0.0; 0498 m1.m[2][1] = -s; 0499 m1.m[2][2] = c; 0500 0501 return m1; 0502 } 0503 0504 Mat3 yrot (double a) 0505 { 0506 // Rotation matrix around y-axis with angle a (in radians). 0507 double c, s; 0508 Mat3 m1; 0509 0510 c = cos (a); 0511 s = sin (a); 0512 m1.m[0][0] = c; 0513 m1.m[0][1] = 0.0; 0514 m1.m[0][2] = -s; 0515 m1.m[1][0] = 0.0; 0516 m1.m[1][1] = 1.0; 0517 m1.m[1][2] = 0.0; 0518 m1.m[2][0] = s; 0519 m1.m[2][1] = 0.0; 0520 m1.m[2][2] = c; 0521 0522 return m1; 0523 } 0524 0525 Mat3 zrot (double a) 0526 { 0527 // Rotation matrix around z-axis with angle a (in radians). 0528 double c, s; 0529 Mat3 m1; 0530 0531 c = cos (a); 0532 s = sin (a); 0533 m1.m[0][0] = c; 0534 m1.m[0][1] = s; 0535 m1.m[0][2] = 0.0; 0536 m1.m[1][0] = -s; 0537 m1.m[1][1] = c; 0538 m1.m[1][2] = 0.0; 0539 m1.m[2][0] = 0.0; 0540 m1.m[2][1] = 0.0; 0541 m1.m[2][2] = 1.0; 0542 0543 return m1; 0544 } 0545 0546 Mat3 csmx (double p, double y, double r) 0547 { 0548 // Form cosine matrix m from pitch p, yaw y and roll r angles. 0549 // The angles are to be given in radians. 0550 // Roll is rotation about the x-axis, pitch about y, yaw about z. 0551 // 0552 Mat3 pitch, yaw, roll, result; 0553 0554 pitch = yrot (p); 0555 yaw = zrot (y); 0556 roll = xrot (r); 0557 result = yaw * pitch; 0558 result *= roll; 0559 0560 return result; 0561 } 0562 0563 void gpyr (const Mat3& m1, double& p, double& y, double& r) 0564 { 0565 // Get pitch p, yaw y and roll r angles (in radians) from 0566 // cosine matrix m1. 0567 0568 y = asin (m1.m[0][1]); 0569 r = atan20 (-m1.m[2][1], m1.m[1][1]); 0570 p = atan20 (-m1.m[0][2], m1.m[0][0]); 0571 } 0572 0573 void vcpy (Vec3& v, double& p, double& y) 0574 { 0575 // Convert direction given by cartesion vector v into a corresponding 0576 // pitch (p) / yaw (y) sequence. The angles are in radians. 0577 0578 p = atan20 (-v[2], v[0]); 0579 y = atan20 (v[1], sqrt (v[0]*v[0] + v[2]*v[2])); 0580 } 0581 0582 void vcrp (Vec3& v, double& p, double& r) 0583 { 0584 // Convert direction given by cartesian vector v into a corresponding 0585 // roll (r) / pitch (p) sequence. The angles are in radians. 0586 0587 r = atan20 (v[1], -v[2]); 0588 p = M_PI / 2.0 - atan20 (v[0], sqrt (v[1]*v[1] + v[2]*v[2])); 0589 } 0590 0591 void mxevc (const Mat3& m, double& a, Vec3& v) 0592 { 0593 // Get eigenvalue a and eigenvector v from cosine matrix m. 0594 // The eigenangle a is in radians. 0595 0596 double ri, rj, rk, q1, q2, q3, q4; 0597 0598 // using the 3-1-3 rotation matrix, first get the corresponding 0599 // angles ri, rj, rk of rotation about the x-, y-, z-axis. 0600 ri = atan20 (m.m[2][0], -m.m[2][1]); 0601 rj = 0.5 * acos (m.m[2][2]); 0602 rk = atan20 (m.m[0][2], m.m[1][2]); 0603 0604 // now convert to quaternions 0605 q4 = sin (rj); 0606 q1 = q4 * cos (0.5 * (ri - rk)); 0607 q2 = q4 * sin (0.5 * (ri - rk)); 0608 q4 = cos (rj); 0609 q3 = q4 * sin (0.5 * (ri + rk)); 0610 q4 = q4 * cos (0.5 * (ri + rk)); 0611 0612 // now get the eigen angle and eigen vector 0613 v.assign(q1, q2, q3); 0614 ri = abs (v); 0615 if (ri == 0) 0616 { 0617 // treat singularity for 3-1-3 matrix 0618 v.assign (0.0, 0.0, 1.0); 0619 q4 = 0.5 * sqrt (1.0 + m.m[0][0] + m.m[1][1] + m.m[2][2]); 0620 } 0621 else v /= ri; 0622 0623 a = 2.0 * acos (q4); 0624 } 0625 0626 Mat3 mxrox (double& a, Vec3& v) 0627 { 0628 // Convert eigenvalue a (eigen angle in radians) and eigenvector v 0629 // into a corresponding cosine rotation matrix m. 0630 0631 double q1, q2, q3, q4, q12, q22, q32, q42; 0632 Mat3 result; 0633 0634 // calculate quaternions and their squares 0635 q4 = sin ( 0.5 * a); 0636 q1 = v[0] * q4; 0637 q2 = v[1] * q4; 0638 q3 = v[2] * q4; 0639 q4 = cos (0.5 * a); 0640 q12 = q1 * q1; 0641 q22 = q2 * q2; 0642 q32 = q3 * q3; 0643 q42 = q4 * q4; 0644 0645 // now get the matrix elements 0646 result.assign ((q12 - q22 - q32 + q42), (2.0 * (q1*q2 + q3*q4)), 0647 (2.0 * (q1*q3 - q2*q4)), (2.0 * (q1*q2 - q3*q4)), 0648 (-q12 + q22 - q32 + q42),(2.0 * (q2*q3 + q1*q4)), 0649 (2.0 * (q1*q3 + q2*q4)), (2.0 * (q2*q3 - q1*q4)), 0650 (-q12 - q22 + q32 + q42)); 0651 0652 return result; 0653 } 0654 0655 0656 ostream& operator << (ostream& os, const Mat3& c) 0657 { 0658 os << "[" << c.m[0][0] << "," << c.m[0][1] << "," << c.m[0][2] << "]" << endl 0659 << "[" << c.m[1][0] << "," << c.m[1][1] << "," << c.m[1][2] << "]" << endl 0660 << "[" << c.m[2][0] << "," << c.m[2][1] << "," << c.m[2][2] << "]" << endl; 0661 return os; 0662 } 0663