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