File indexing completed on 2024-04-21 03:48: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