File indexing completed on 2024-05-12 15:23:44

0001 /*
0002     SPDX-FileCopyrightText: 2012 Andrew Stepanenko
0003 
0004     Modified by Jasem Mutlaq <mutlaqja@ikarustech.com> for KStars:
0005     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "matr.h"
0011 
0012 #include "vect.h"
0013 
0014 #include <cmath>
0015 
0016 namespace GuiderUtils
0017 {
0018 Matrix ::Matrix(double v)
0019 {
0020     for (int i = 0; i < 4; i++)
0021         for (int j = 0; j < 4; j++)
0022             x[i][j] = (i == j) ? v : 0.0;
0023     x[3][3] = 1;
0024 }
0025 
0026 Matrix ::Matrix()
0027 {
0028     for (auto &row : x)
0029         for (double &item : row)
0030         {
0031             item = 0.0;
0032         }
0033 
0034     x[3][3] = 1;
0035 }
0036 
0037 void Matrix ::Invert()
0038 {
0039     Matrix Out(1);
0040     for (int i = 0; i < 4; i++)
0041     {
0042         double d = x[i][i];
0043         if (d != 1.0)
0044         {
0045             for (int j = 0; j < 4; j++)
0046             {
0047                 Out.x[i][j] /= d;
0048                 x[i][j] /= d;
0049             }
0050         }
0051 
0052         for (int j = 0; j < 4; j++)
0053         {
0054             if (j != i)
0055             {
0056                 if (x[j][i] != 0.0)
0057                 {
0058                     double mulby = x[j][i];
0059                     for (int k = 0; k < 4; k++)
0060                     {
0061                         x[j][k] -= mulby * x[i][k];
0062                         Out.x[j][k] -= mulby * Out.x[i][k];
0063                     }
0064                 }
0065             }
0066         }
0067     }
0068     *this = Out;
0069 }
0070 
0071 void Matrix ::Transpose()
0072 {
0073     double t;
0074     for (int i = 0; i < 4; i++)
0075         for (int j = i; j < 4; j++)
0076             if (i != j)
0077             {
0078                 t       = x[i][j];
0079                 x[i][j] = x[j][i];
0080                 x[j][i] = t;
0081             }
0082 }
0083 
0084 Matrix &Matrix ::operator+=(const Matrix &A)
0085 {
0086     if (this == &A)
0087         return *this;
0088 
0089     for (int i = 0; i < 4; i++)
0090         for (int j = 0; j < 4; j++)
0091             x[i][j] += A.x[i][j];
0092 
0093     return *this;
0094 }
0095 
0096 Matrix &Matrix ::operator-=(const Matrix &A)
0097 {
0098     if (this == &A)
0099         return *this;
0100 
0101     for (int i = 0; i < 4; i++)
0102         for (int j = 0; j < 4; j++)
0103             x[i][j] -= A.x[i][j];
0104 
0105     return *this;
0106 }
0107 
0108 Matrix &Matrix ::operator*=(double v)
0109 {
0110     for (auto &row : x)
0111         for (double &item : row)
0112         {
0113             item *= v;
0114         }
0115 
0116     return *this;
0117 }
0118 
0119 Matrix &Matrix ::operator*=(const Matrix &A)
0120 {
0121     if (this == &A)
0122         return *this;
0123 
0124     Matrix res = *this;
0125     for (int i = 0; i < 4; i++)
0126         for (int j = 0; j < 4; j++)
0127         {
0128             double sum = 0;
0129             for (int k = 0; k < 4; k++)
0130                 sum += res.x[i][k] * A.x[k][j];
0131 
0132             x[i][j] = sum;
0133         }
0134     return *this;
0135 }
0136 
0137 Matrix operator+(const Matrix &A, const Matrix &B)
0138 {
0139     Matrix res;
0140     for (int i = 0; i < 4; i++)
0141         for (int j = 0; j < 4; j++)
0142             res.x[i][j] = A.x[i][j] + B.x[i][j];
0143 
0144     return res;
0145 }
0146 
0147 Matrix operator-(const Matrix &A, const Matrix &B)
0148 {
0149     Matrix res;
0150     for (int i = 0; i < 4; i++)
0151         for (int j = 0; j < 4; j++)
0152             res.x[i][j] = A.x[i][j] - B.x[i][j];
0153 
0154     return res;
0155 }
0156 
0157 Matrix operator*(const Matrix &A, const Matrix &B)
0158 {
0159     Matrix res;
0160     for (int i = 0; i < 4; i++)
0161         for (int j = 0; j < 4; j++)
0162         {
0163             double sum = 0;
0164             for (int k = 0; k < 4; k++)
0165                 sum += A.x[i][k] * B.x[k][j];
0166 
0167             res.x[i][j] = sum;
0168         }
0169 
0170     return res;
0171 }
0172 
0173 Matrix operator*(const Matrix &A, double v)
0174 {
0175     Matrix res;
0176     for (int i = 0; i < 4; i++)
0177         for (int j = 0; j < 4; j++)
0178             res.x[i][j] = A.x[i][j] * v;
0179 
0180     return res;
0181 }
0182 
0183 GuiderUtils::Vector operator*(const GuiderUtils::Vector &v, const Matrix &M)
0184 {
0185     GuiderUtils::Vector res;
0186 
0187     res.x = v.x * M.x[0][0] + v.y * M.x[0][1] + v.z * M.x[0][2] + M.x[0][3];
0188     res.y = v.x * M.x[1][0] + v.y * M.x[1][1] + v.z * M.x[1][2] + M.x[1][3];
0189     res.z = v.x * M.x[2][0] + v.y * M.x[2][1] + v.z * M.x[2][2] + M.x[2][3];
0190     /*
0191      res.x = v.x*M.x[0][0] + v.y*M.x[1][0] + v.z*M.x[2][0] + M.x[3][0];
0192      res.y = v.x*M.x[0][1] + v.y*M.x[1][1] + v.z*M.x[2][1] + M.x[3][1];
0193      res.z = v.x*M.x[0][2] + v.y*M.x[1][2] + v.z*M.x[2][2] + M.x[3][2];
0194 
0195      double denom = v.x*M.x[0][3] + v.y*M.x[1][3] + v.z*M.x[2][3] + M.x[3][3];
0196      if( denom != 1.0 )
0197      {
0198          res /= denom;
0199          ShowMessage("denom="+FloatToStr(denom));
0200      }
0201     */
0202     //  ShowMessage( FloatToStr(v.x)+"\n" + FloatToStr(v.x)+"\n" + FloatToStr(v.x) );
0203     //  ShowMessage("res.x="+FloatToStr(res.x)+"\nres.y="+FloatToStr(res.y));
0204     /*
0205       ShowMessage( FloatToStr(M.x[0][0])+", " + FloatToStr(M.x[1][0])+", " + FloatToStr(M.x[2][0])+", " + FloatToStr(M.x[3][0])+"\n" +
0206                    FloatToStr(M.x[0][1])+", " + FloatToStr(M.x[1][1])+", " + FloatToStr(M.x[2][1])+", " + FloatToStr(M.x[3][1])+"\n" +
0207                    FloatToStr(M.x[0][2])+", " + FloatToStr(M.x[1][2])+", " + FloatToStr(M.x[2][2])+", " + FloatToStr(M.x[3][2])+"\n" +
0208                    FloatToStr(M.x[0][3])+", " + FloatToStr(M.x[1][3])+", " + FloatToStr(M.x[2][3])+", " + FloatToStr(M.x[3][3])+"\n"
0209                  );
0210     */
0211     return res;
0212 }
0213 
0214 Matrix Translate(const GuiderUtils::Vector &Loc)
0215 {
0216     Matrix res(1);
0217     res.x[0][3] = Loc.x;
0218     res.x[1][3] = Loc.y;
0219     res.x[2][3] = Loc.z;
0220     /*
0221      res.x[3][0] = Loc.x;
0222      res.x[3][1] = Loc.y;
0223      res.x[3][2] = Loc.z;
0224     */
0225     return res;
0226 }
0227 
0228 Matrix Scale(const GuiderUtils::Vector &v)
0229 {
0230     Matrix res(1);
0231     res.x[0][0] = v.x;
0232     res.x[1][1] = v.y;
0233     res.x[2][2] = v.z;
0234 
0235     return res;
0236 }
0237 
0238 Matrix RotateX(double Angle)
0239 {
0240     Matrix res(1);
0241     double Cosine = cos(Angle);
0242     double Sine   = sin(Angle);
0243 
0244     res.x[1][1] = Cosine;
0245     res.x[2][1] = Sine;
0246     res.x[1][2] = -Sine;
0247     res.x[2][2] = Cosine;
0248     /*
0249      res.x[1][1] = Cosine;
0250      res.x[2][1] = -Sine;
0251      res.x[1][2] = Sine;
0252      res.x[2][2] = Cosine;
0253     */
0254     return res;
0255 }
0256 
0257 Matrix RotateY(double Angle)
0258 {
0259     Matrix res(1);
0260     double Cosine = cos(Angle);
0261     double Sine   = sin(Angle);
0262 
0263     res.x[0][0] = Cosine;
0264     res.x[2][0] = Sine;  //-
0265     res.x[0][2] = -Sine; //+
0266     res.x[2][2] = Cosine;
0267 
0268     return res;
0269 }
0270 
0271 Matrix RotateZ(double Angle)
0272 {
0273     Matrix res(1);
0274     double Cosine = cos(Angle);
0275     double Sine   = sin(Angle);
0276 
0277     // ShowMessage( "sin="+FloatToStr(Sine)+"\ncos="+FloatToStr(Cosine) );
0278 
0279     res.x[0][0] = Cosine;
0280     res.x[1][0] = Sine;  //-
0281     res.x[0][1] = -Sine; //+
0282     res.x[1][1] = Cosine;
0283 
0284     return res;
0285 }
0286 
0287 Matrix Rotate(const GuiderUtils::Vector &axis, double angle)
0288 {
0289     Matrix res(1);
0290     double Cosine = cos(angle);
0291     double Sine   = sin(angle);
0292 
0293     res.x[0][0] = axis.x * axis.x + (1 - axis.x * axis.x) * Cosine;
0294     res.x[0][1] = axis.x * axis.y * (1 - Cosine) + axis.z * Sine;
0295     res.x[0][2] = axis.x * axis.z * (1 - Cosine) - axis.y * Sine;
0296     res.x[0][3] = 0;
0297 
0298     res.x[1][0] = axis.x * axis.y * (1 - Cosine) - axis.z * Sine;
0299     res.x[1][1] = axis.y * axis.y + (1 - axis.y * axis.y) * Cosine;
0300     res.x[1][2] = axis.y * axis.z * (1 - Cosine) + axis.x * Sine;
0301     res.x[1][3] = 0;
0302 
0303     res.x[2][0] = axis.x * axis.z * (1 - Cosine) + axis.y * Sine;
0304     res.x[2][1] = axis.y * axis.z * (1 - Cosine) - axis.x * Sine;
0305     res.x[2][2] = axis.z * axis.z + (1 - axis.z * axis.z) * Cosine;
0306     res.x[2][3] = 0;
0307 
0308     res.x[3][0] = 0;
0309     res.x[3][1] = 0;
0310     res.x[3][2] = 0;
0311     res.x[3][3] = 1;
0312 
0313     return res;
0314 }
0315 // Transforms V into coord sys. v1, v2, v3
0316 Matrix Transform(const GuiderUtils::Vector &v1, const GuiderUtils::Vector &v2, const GuiderUtils::Vector &v3)
0317 {
0318     Matrix res(1);
0319 
0320     // Flipped columns & rows vs prev version
0321     res.x[0][0] = v1.x;
0322     res.x[0][1] = v1.y;
0323     res.x[0][2] = v1.z;
0324     res.x[0][3] = 0;
0325 
0326     res.x[1][0] = v2.x;
0327     res.x[1][1] = v2.y;
0328     res.x[1][2] = v2.z;
0329     res.x[1][3] = 0;
0330 
0331     res.x[2][0] = v3.x;
0332     res.x[2][1] = v3.y;
0333     res.x[2][2] = v3.z;
0334     res.x[2][3] = 0;
0335 
0336     res.x[3][0] = 0;
0337     res.x[3][1] = 0;
0338     res.x[3][2] = 0;
0339     res.x[3][3] = 1;
0340 
0341     return res;
0342 }
0343 
0344 Matrix MirrorX()
0345 {
0346     Matrix res(1);
0347     res.x[0][0] = -1;
0348     return res;
0349 }
0350 
0351 Matrix MirrorY()
0352 {
0353     Matrix res(1);
0354     res.x[1][1] = -1;
0355     return res;
0356 }
0357 
0358 Matrix MirrorZ()
0359 {
0360     Matrix res(1);
0361     res.x[2][2] = -1;
0362     return res;
0363 }
0364 }  // namespace GuiderUtils