gVirtualXRay  2.0.10
VirtualX-RayImagingLibraryonGPU
Matrix4x4.inl
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2014-2023, Dr Franck P. Vidal, Bangor University, All rights reserved.
4 Copyright (c) 2023-present, Prof Franck P. Vidal (franck.vidal@stfc.ac.uk),
5 UK Research and Innovation, All rights reserved.
6 
7 
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
17 
18 3. Neither the name of Bangor University, UK Research and Innovation nor the
19 names of its contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 */
34 
35 
64 //******************************************************************************
65 // Include
66 //******************************************************************************
67 #ifndef __ConstantValues_h
69 #endif
70 
71 #include <iostream>
72 #include <cmath>
73 #include <cstring>
74 
75 #ifndef __Exception_h
76 #include "gVirtualXRay/Exception.h"
77 #endif
78 
79 
80 //******************************************************************************
81 // namespace
82 //******************************************************************************
83 namespace gVirtualXRay {
84 
85 
86 //----------------------------------------------------------------------------------------------
87 template<typename T> Matrix4x4<T>::Matrix4x4(const T& a1, const T& a2, const T& a3, const T& a4,
88  const T& a5, const T& a6, const T& a7, const T& a8,
89  const T& a9, const T& a10, const T& a11, const T& a12,
90  const T& a13, const T& a14, const T& a15, const T& a16):
91 //----------------------------------------------------------------------------------------------
92  m_small_matrix_up_to_date(false)
93 //----------------------------------------------------------------------------------------------
94 {
95  m_p_4x4_data[0] = a1;
96  m_p_4x4_data[1] = a2;
97  m_p_4x4_data[2] = a3;
98  m_p_4x4_data[3] = a4;
99  m_p_4x4_data[4] = a5;
100  m_p_4x4_data[5] = a6;
101  m_p_4x4_data[6] = a7;
102  m_p_4x4_data[7] = a8;
103  m_p_4x4_data[8] = a9;
104  m_p_4x4_data[9] = a10;
105  m_p_4x4_data[10] = a11;
106  m_p_4x4_data[11] = a12;
107  m_p_4x4_data[12] = a13;
108  m_p_4x4_data[13] = a14;
109  m_p_4x4_data[14] = a15;
110  m_p_4x4_data[15] = a16;
111 }
112 
113 
114 //---------------------------------------------------------------------
115 template<typename T> Matrix4x4<T>::Matrix4x4(const Matrix4x4& aMatrix):
116 //---------------------------------------------------------------------
117  m_small_matrix_up_to_date(false)
118 //---------------------------------------------------------------------
119 {
120  memcpy(m_p_4x4_data, aMatrix.m_p_4x4_data, sizeof(m_p_4x4_data));
121 }
122 
123 
124 //--------------------------------------------------------------
125 template<typename T> Matrix4x4<T>::Matrix4x4(const T* apMatrix):
126 //--------------------------------------------------------------
127  m_small_matrix_up_to_date(false)
128 //--------------------------------------------------------------
129 {
130  memcpy(m_p_4x4_data, apMatrix, sizeof(m_p_4x4_data));
131 }
132 
133 
134 //--------------------------------------------------------------------------------
135 template<typename T> Matrix4x4<T>::Matrix4x4(const std::vector<double>& apMatrix):
136 //--------------------------------------------------------------------------------
137  m_small_matrix_up_to_date(false)
138 //--------------------------------------------------------------------------------
139 {
140  if (apMatrix.size() != 16)
141  {
142  throw Exception(__FILE__, __FUNCTION__, __LINE__, "The input matrix is not 4x4.");
143  }
144 
145  for (unsigned int i = 0; i < 16; ++i)
146  m_p_4x4_data[i] = apMatrix[i];
147 }
148 
149 
150 //----------------------------------------------------
151 template<typename T> void Matrix4x4<T>::loadIdentity()
152 //----------------------------------------------------
153 {
154  m_p_4x4_data[0] = 1.0;
155  m_p_4x4_data[1] = 0.0;
156  m_p_4x4_data[2] = 0.0;
157  m_p_4x4_data[3] = 0.0;
158 
159  m_p_4x4_data[4] = 0.0;
160  m_p_4x4_data[5] = 1.0;
161  m_p_4x4_data[6] = 0.0;
162  m_p_4x4_data[7] = 0.0;
163 
164  m_p_4x4_data[8] = 0.0;
165  m_p_4x4_data[9] = 0.0;
166  m_p_4x4_data[10] = 1.0;
167  m_p_4x4_data[11] = 0.0;
168 
169  m_p_4x4_data[12] = 0.0;
170  m_p_4x4_data[13] = 0.0;
171  m_p_4x4_data[14] = 0.0;
172  m_p_4x4_data[15] = 1.0;
173 
174  m_small_matrix_up_to_date = false;
175 }
176 
177 
178 //----------------------------------------------------------------------------------------
179 template<typename T>void Matrix4x4<T>::setFromVector(const std::vector<double>& apMatrix)
180 //----------------------------------------------------------------------------------------
181 {
182  if (apMatrix.size() != 16)
183  {
184  throw Exception(__FILE__, __FUNCTION__, __LINE__, "The input matrix is not 4x4.");
185  }
186 
187  m_small_matrix_up_to_date = false;
188 
189  for (unsigned int i = 0; i < 16; ++i)
190  m_p_4x4_data[i] = apMatrix[i];
191 }
192 
193 
194 //------------------------------------------------------------------------------------------
195 template<typename T> void Matrix4x4<T>::rotate(const double anAngle, const Vec3<T>& aVector)
196 //------------------------------------------------------------------------------------------
197 {
198  *this *= buildRotationMatrix(anAngle, aVector);
199 
200  m_small_matrix_up_to_date = false;
201 }
202 
203 
204 //----------------------------------------------------------------------
205 template<typename T> void Matrix4x4<T>::yawPitchRollRotate(double yaw,
206  double pitch,
207  double roll)
208 //----------------------------------------------------------------------
209 {
210  *this *= buildYawPitchRollRotationMatrix(yaw, pitch, roll);
211 
212  m_small_matrix_up_to_date = false;
213 }
214 
215 
216 //-----------------------------------------------------------------------
217 template<typename T> void Matrix4x4<T>::translate(const Vec3<T>& aVector)
218 //-----------------------------------------------------------------------
219 {
220  *this *= buildTranslationMatrix(aVector);
221 
222  m_small_matrix_up_to_date = false;
223 }
224 
225 
226 //--------------------------------------------------------------
227 template<typename T> void Matrix4x4<T>::translate(T x, T y, T z)
228 //--------------------------------------------------------------
229 {
230  *this *= buildTranslationMatrix(x, y, z);
231 
232  m_small_matrix_up_to_date = false;
233 }
234 
235 
236 //-------------------------------------------------------------------
238 //-------------------------------------------------------------------
239 {
240  return (Matrix4x4<T>(
241  1.0, 0.0, 0.0, 0.0,
242  0.0, 1.0, 0.0, 0.0,
243  0.0, 0.0, 1.0, 0.0,
244  0.0, 0.0, 0.0, 1.0));
245 }
246 
247 
248 //--------------------------------------------------------------------------------------------
249 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildTranslationMatrix(const Vec3<T>& aVector)
250 //--------------------------------------------------------------------------------------------
251 {
252  return (buildTranslationMatrix(aVector.getX(), aVector.getY(), aVector.getZ()));
253 }
254 
255 
256 //-----------------------------------------------------------------------------------
257 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildTranslationMatrix(T x, T y, T z)
258 //-----------------------------------------------------------------------------------
259 {
260  return (Matrix4x4<T>(
261  1.0, 0.0, 0.0, 0.0,
262  0.0, 1.0, 0.0, 0.0,
263  0.0, 0.0, 1.0, 0.0,
264  x, y, z, 1.0));
265 }
266 
267 //--------------------------------------------------------------------------------------------
268 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildScaleMatrix( const Vec3<T>& aVector )
269 //--------------------------------------------------------------------------------------------
270 {
271  return ( buildScaleMatrix( aVector.getX( ), aVector.getY( ), aVector.getZ( ) ) );
272 }
273 
274 
275 //-----------------------------------------------------------------------------------
276 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildScaleMatrix( T x, T y, T z )
277 //-----------------------------------------------------------------------------------
278 {
279  // Make sure not all the scaling factors are null
280  Vec3<T> temp(Vec3<T>(x, y, z));
281  if (temp.length() < 1e-9)
282  {
283  std::stringstream error_message;
284  error_message << "Invalid scaling factors, all of them are null: " << temp;
285  throw Exception(__FILE__, __FUNCTION__, __LINE__, error_message.str());
286  }
287 
288  return ( Matrix4x4<T>(
289  x, 0.0, 0.0, 0.0,
290  0.0, y, 0.0, 0.0,
291  0.0, 0.0, z, 0.0,
292  0.0, 0.0, 0.0, 1.0 ) );
293 }
294 
295 
296 
297 //-----------------------------------------------------------------------------------------
298 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildRotationMatrix(T anAngle,
299  const Vec3<T>& aVector)
300 //-----------------------------------------------------------------------------------------
301 {
302  return (buildRotationMatrix(anAngle, aVector.getX(), aVector.getY(), aVector.getZ()));
303 }
304 
305 
306 //--------------------------------------------------------------------------------
307 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildRotationMatrix(T anAngle,
308  T x, T y, T z)
309 //--------------------------------------------------------------------------------
310 {
311  Vec3<T> temp_rotation_axis(Vec3<T>(x, y, z));
312 
313  // Make sure the length of the vector is not null
314  if (temp_rotation_axis.length() < 1e-9)
315  {
316  std::stringstream error_message;
317  error_message << "Invalid rotation axis, (" << temp_rotation_axis << ")'s length is zero.";
318  throw Exception(__FILE__, __FUNCTION__, __LINE__, error_message.str());
319  }
320 
321  Vec3<T> rotation_axis(temp_rotation_axis.normal());
322  double angle(Pi * anAngle / 180.0);
323  double c(cos(angle));
324  double s(sin(angle));
325  double one_minus_cos(1.0 - c);
326  double xy(rotation_axis.getX() * rotation_axis.getY());
327  double xz(rotation_axis.getX() * rotation_axis.getZ());
328  double yz(rotation_axis.getY() * rotation_axis.getZ());
329 
330  Matrix4x4<T> rotation_matrix(
331  rotation_axis.getX() * rotation_axis.getX() * (1.0 - c) + c,
332  xy * one_minus_cos + rotation_axis.getZ() * s,
333  xz * one_minus_cos - rotation_axis.getY() * s,
334  0.0,
335 
336  xy * one_minus_cos - rotation_axis.getZ() * s,
337  rotation_axis.getY() * rotation_axis.getY() * one_minus_cos + c,
338  yz * one_minus_cos + rotation_axis.getX() * s,
339  0.0,
340 
341  xz * one_minus_cos + rotation_axis.getY() * s,
342  yz * one_minus_cos - rotation_axis.getX() * s,
343  rotation_axis.getZ() * rotation_axis.getZ() * one_minus_cos + c,
344  0.0,
345 
346  0.0,
347  0.0,
348  0.0,
349  1.0);
350 
351  return (rotation_matrix);
352 }
353 
354 
355 //-----------------------------------------------------------------------------------------------------
356 template<typename T> Matrix4x4<T> Matrix4x4<T>::buildYawPitchRollRotationMatrix(T yaw, T pitch, T roll)
357 //-----------------------------------------------------------------------------------------------------
358 {
359  T alpha = Pi * yaw / 180.0;
360  T cos_alpha = cos(alpha);
361  T sin_alpha = sin(alpha);
362 
363  T beta = Pi * pitch / 180.0;
364  T cos_beta = cos(beta);
365  T sin_beta = sin(beta);
366 
367  T gamma = Pi * roll / 180.0;
368  T cos_gamma = cos(gamma);
369  T sin_gamma = sin(gamma);
370 
371 
372  Matrix4x4<T> rotation_matrix(
373  cos_alpha * cos_beta,
374  sin_alpha * cos_beta,
375  -sin_beta,
376  0.0,
377 
378  cos_alpha * sin_beta * sin_gamma - sin_alpha * cos_gamma,
379  sin_alpha * sin_beta * sin_gamma + cos_alpha * cos_gamma,
380  cos_beta * sin_gamma,
381  0.0,
382 
383  cos_alpha * sin_beta * cos_gamma + sin_alpha * sin_gamma,
384  sin_alpha * sin_beta * cos_gamma - cos_alpha * sin_gamma,
385  cos_beta * cos_gamma,
386  0.0,
387 
388  0.0,
389  0.0,
390  0.0,
391  1.0);
392 
393  return (rotation_matrix);
394 }
395 
396 
397 
398 //----------------------------------------------------------
399 template<typename T> void Matrix4x4<T>::scale(T x, T y, T z)
400 //----------------------------------------------------------
401 {
402  // Make sure not all the scaling factors are null
403  Vec3<T> temp(Vec3<T>(x, y, z));
404  if (temp.length() < 1e-9)
405  {
406  std::stringstream error_message;
407  error_message << "Invalid scaling factors, all of them are null: " << temp;
408  throw Exception(__FILE__, __FUNCTION__, __LINE__, error_message.str());
409  }
410 
411  Matrix4x4<T> scaling_matrix(
412  x, 0.0, 0.0, 0.0,
413  0.0, y, 0.0, 0.0,
414  0.0, 0.0, z, 0.0,
415  0.0, 0.0, 0.0, 1.0);
416 
417  *this *= scaling_matrix;
418 
419  m_small_matrix_up_to_date = false;
420 }
421 
422 
423 //------------------------------------------------------------------
424 template<typename T> Matrix4x4<T> Matrix4x4<T>::getTranspose() const
425 //------------------------------------------------------------------
426 {
427  return Matrix4x4<T>(
428  m_p_4x4_data[0], m_p_4x4_data[4], m_p_4x4_data[8], m_p_4x4_data[12],
429  m_p_4x4_data[1], m_p_4x4_data[5], m_p_4x4_data[9], m_p_4x4_data[13],
430  m_p_4x4_data[2], m_p_4x4_data[6], m_p_4x4_data[10], m_p_4x4_data[14],
431  m_p_4x4_data[3], m_p_4x4_data[7], m_p_4x4_data[11], m_p_4x4_data[15]);
432 }
433 
434 
435  //-----------------------------------------------------
436 template<typename T> T Matrix4x4<T>::determinant() const
437 //------------------------------------------------------
438 {
439  return
440  m_p_4x4_data[3] * m_p_4x4_data[6] * m_p_4x4_data[9] * m_p_4x4_data[12] - m_p_4x4_data[2] * m_p_4x4_data[7] * m_p_4x4_data[9] * m_p_4x4_data[12] - m_p_4x4_data[3] * m_p_4x4_data[5] * m_p_4x4_data[10] * m_p_4x4_data[12]+m_p_4x4_data[1] * m_p_4x4_data[7] * m_p_4x4_data[10] * m_p_4x4_data[12]+
441  m_p_4x4_data[2] * m_p_4x4_data[5] * m_p_4x4_data[11] * m_p_4x4_data[12] - m_p_4x4_data[1] * m_p_4x4_data[6] * m_p_4x4_data[11] * m_p_4x4_data[12] - m_p_4x4_data[3] * m_p_4x4_data[6] * m_p_4x4_data[8] * m_p_4x4_data[13]+m_p_4x4_data[2] * m_p_4x4_data[7] * m_p_4x4_data[8] * m_p_4x4_data[13]+
442  m_p_4x4_data[3] * m_p_4x4_data[4] * m_p_4x4_data[10] * m_p_4x4_data[13] - m_p_4x4_data[0] * m_p_4x4_data[7] * m_p_4x4_data[10] * m_p_4x4_data[13] - m_p_4x4_data[2] * m_p_4x4_data[4] * m_p_4x4_data[11] * m_p_4x4_data[13]+m_p_4x4_data[0] * m_p_4x4_data[6] * m_p_4x4_data[11] * m_p_4x4_data[13]+
443  m_p_4x4_data[3] * m_p_4x4_data[5] * m_p_4x4_data[8] * m_p_4x4_data[14] - m_p_4x4_data[1] * m_p_4x4_data[7] * m_p_4x4_data[8] * m_p_4x4_data[14] - m_p_4x4_data[3] * m_p_4x4_data[4] * m_p_4x4_data[9] * m_p_4x4_data[14]+m_p_4x4_data[0] * m_p_4x4_data[7] * m_p_4x4_data[9] * m_p_4x4_data[14]+
444  m_p_4x4_data[1] * m_p_4x4_data[4] * m_p_4x4_data[11] * m_p_4x4_data[14] - m_p_4x4_data[0] * m_p_4x4_data[5] * m_p_4x4_data[11] * m_p_4x4_data[14] - m_p_4x4_data[2] * m_p_4x4_data[5] * m_p_4x4_data[8] * m_p_4x4_data[15]+m_p_4x4_data[1] * m_p_4x4_data[6] * m_p_4x4_data[8] * m_p_4x4_data[15]+
445  m_p_4x4_data[2] * m_p_4x4_data[4] * m_p_4x4_data[9] * m_p_4x4_data[15] - m_p_4x4_data[0] * m_p_4x4_data[6] * m_p_4x4_data[9] * m_p_4x4_data[15] - m_p_4x4_data[1] * m_p_4x4_data[4] * m_p_4x4_data[10] * m_p_4x4_data[15]+m_p_4x4_data[0] * m_p_4x4_data[5] * m_p_4x4_data[10] * m_p_4x4_data[15];
446 }
447 
448 
449 //----------------------------------------------------------------
450 template<typename T> Matrix4x4<T> Matrix4x4<T>::getInverse() const
451 //----------------------------------------------------------------
452 {
453  T m0(0), m1(0), m2(0), m3(0), m4(0), m5(0), m6(0), m7(0), m8(0), m9(0), m10(0), m11(0), m12(0), m13(0), m14(0), m15(0);
454  T matrix_determinant(determinant());
455 
456  if (fabs(matrix_determinant) > 0.000001)
457  {
458  m0 = (m_p_4x4_data[6]*m_p_4x4_data[11]*m_p_4x4_data[13] - m_p_4x4_data[7]*m_p_4x4_data[10]*m_p_4x4_data[13] + m_p_4x4_data[7]*m_p_4x4_data[9]*m_p_4x4_data[14] - m_p_4x4_data[5]*m_p_4x4_data[11]*m_p_4x4_data[14] - m_p_4x4_data[6]*m_p_4x4_data[9]*m_p_4x4_data[15] + m_p_4x4_data[5]*m_p_4x4_data[10]*m_p_4x4_data[15]) / matrix_determinant;
459  m1 = (m_p_4x4_data[3]*m_p_4x4_data[10]*m_p_4x4_data[13] - m_p_4x4_data[2]*m_p_4x4_data[11]*m_p_4x4_data[13] - m_p_4x4_data[3]*m_p_4x4_data[9]*m_p_4x4_data[14] + m_p_4x4_data[1]*m_p_4x4_data[11]*m_p_4x4_data[14] + m_p_4x4_data[2]*m_p_4x4_data[9]*m_p_4x4_data[15] - m_p_4x4_data[1]*m_p_4x4_data[10]*m_p_4x4_data[15]) / matrix_determinant;
460  m2 = (m_p_4x4_data[2]*m_p_4x4_data[7]*m_p_4x4_data[13] - m_p_4x4_data[3]*m_p_4x4_data[6]*m_p_4x4_data[13] + m_p_4x4_data[3]*m_p_4x4_data[5]*m_p_4x4_data[14] - m_p_4x4_data[1]*m_p_4x4_data[7]*m_p_4x4_data[14] - m_p_4x4_data[2]*m_p_4x4_data[5]*m_p_4x4_data[15] + m_p_4x4_data[1]*m_p_4x4_data[6]*m_p_4x4_data[15]) / matrix_determinant;
461  m3 = (m_p_4x4_data[3]*m_p_4x4_data[6]*m_p_4x4_data[9] - m_p_4x4_data[2]*m_p_4x4_data[7]*m_p_4x4_data[9] - m_p_4x4_data[3]*m_p_4x4_data[5]*m_p_4x4_data[10] + m_p_4x4_data[1]*m_p_4x4_data[7]*m_p_4x4_data[10] + m_p_4x4_data[2]*m_p_4x4_data[5]*m_p_4x4_data[11] - m_p_4x4_data[1]*m_p_4x4_data[6]*m_p_4x4_data[11]) / matrix_determinant;
462  m4 = (m_p_4x4_data[7]*m_p_4x4_data[10]*m_p_4x4_data[12] - m_p_4x4_data[6]*m_p_4x4_data[11]*m_p_4x4_data[12] - m_p_4x4_data[7]*m_p_4x4_data[8]*m_p_4x4_data[14] + m_p_4x4_data[4]*m_p_4x4_data[11]*m_p_4x4_data[14] + m_p_4x4_data[6]*m_p_4x4_data[8]*m_p_4x4_data[15] - m_p_4x4_data[4]*m_p_4x4_data[10]*m_p_4x4_data[15]) / matrix_determinant;
463  m5 = (m_p_4x4_data[2]*m_p_4x4_data[11]*m_p_4x4_data[12] - m_p_4x4_data[3]*m_p_4x4_data[10]*m_p_4x4_data[12] + m_p_4x4_data[3]*m_p_4x4_data[8]*m_p_4x4_data[14] - m_p_4x4_data[0]*m_p_4x4_data[11]*m_p_4x4_data[14] - m_p_4x4_data[2]*m_p_4x4_data[8]*m_p_4x4_data[15] + m_p_4x4_data[0]*m_p_4x4_data[10]*m_p_4x4_data[15]) / matrix_determinant;
464  m6 = (m_p_4x4_data[3]*m_p_4x4_data[6]*m_p_4x4_data[12] - m_p_4x4_data[2]*m_p_4x4_data[7]*m_p_4x4_data[12] - m_p_4x4_data[3]*m_p_4x4_data[4]*m_p_4x4_data[14] + m_p_4x4_data[0]*m_p_4x4_data[7]*m_p_4x4_data[14] + m_p_4x4_data[2]*m_p_4x4_data[4]*m_p_4x4_data[15] - m_p_4x4_data[0]*m_p_4x4_data[6]*m_p_4x4_data[15]) / matrix_determinant;
465  m7 = (m_p_4x4_data[2]*m_p_4x4_data[7]*m_p_4x4_data[8] - m_p_4x4_data[3]*m_p_4x4_data[6]*m_p_4x4_data[8] + m_p_4x4_data[3]*m_p_4x4_data[4]*m_p_4x4_data[10] - m_p_4x4_data[0]*m_p_4x4_data[7]*m_p_4x4_data[10] - m_p_4x4_data[2]*m_p_4x4_data[4]*m_p_4x4_data[11] + m_p_4x4_data[0]*m_p_4x4_data[6]*m_p_4x4_data[11]) / matrix_determinant;
466  m8 = (m_p_4x4_data[5]*m_p_4x4_data[11]*m_p_4x4_data[12] - m_p_4x4_data[7]*m_p_4x4_data[9]*m_p_4x4_data[12] + m_p_4x4_data[7]*m_p_4x4_data[8]*m_p_4x4_data[13] - m_p_4x4_data[4]*m_p_4x4_data[11]*m_p_4x4_data[13] - m_p_4x4_data[5]*m_p_4x4_data[8]*m_p_4x4_data[15] + m_p_4x4_data[4]*m_p_4x4_data[9]*m_p_4x4_data[15]) / matrix_determinant;
467  m9 = (m_p_4x4_data[3]*m_p_4x4_data[9]*m_p_4x4_data[12] - m_p_4x4_data[1]*m_p_4x4_data[11]*m_p_4x4_data[12] - m_p_4x4_data[3]*m_p_4x4_data[8]*m_p_4x4_data[13] + m_p_4x4_data[0]*m_p_4x4_data[11]*m_p_4x4_data[13] + m_p_4x4_data[1]*m_p_4x4_data[8]*m_p_4x4_data[15] - m_p_4x4_data[0]*m_p_4x4_data[9]*m_p_4x4_data[15]) / matrix_determinant;
468  m10 = (m_p_4x4_data[1]*m_p_4x4_data[7]*m_p_4x4_data[12] - m_p_4x4_data[3]*m_p_4x4_data[5]*m_p_4x4_data[12] + m_p_4x4_data[3]*m_p_4x4_data[4]*m_p_4x4_data[13] - m_p_4x4_data[0]*m_p_4x4_data[7]*m_p_4x4_data[13] - m_p_4x4_data[1]*m_p_4x4_data[4]*m_p_4x4_data[15] + m_p_4x4_data[0]*m_p_4x4_data[5]*m_p_4x4_data[15]) / matrix_determinant;
469  m11 = (m_p_4x4_data[3]*m_p_4x4_data[5]*m_p_4x4_data[8] - m_p_4x4_data[1]*m_p_4x4_data[7]*m_p_4x4_data[8] - m_p_4x4_data[3]*m_p_4x4_data[4]*m_p_4x4_data[9] + m_p_4x4_data[0]*m_p_4x4_data[7]*m_p_4x4_data[9] + m_p_4x4_data[1]*m_p_4x4_data[4]*m_p_4x4_data[11] - m_p_4x4_data[0]*m_p_4x4_data[5]*m_p_4x4_data[11]) / matrix_determinant;
470  m12 = (m_p_4x4_data[6]*m_p_4x4_data[9]*m_p_4x4_data[12] - m_p_4x4_data[5]*m_p_4x4_data[10]*m_p_4x4_data[12] - m_p_4x4_data[6]*m_p_4x4_data[8]*m_p_4x4_data[13] + m_p_4x4_data[4]*m_p_4x4_data[10]*m_p_4x4_data[13] + m_p_4x4_data[5]*m_p_4x4_data[8]*m_p_4x4_data[14] - m_p_4x4_data[4]*m_p_4x4_data[9]*m_p_4x4_data[14]) / matrix_determinant;
471  m13 = (m_p_4x4_data[1]*m_p_4x4_data[10]*m_p_4x4_data[12] - m_p_4x4_data[2]*m_p_4x4_data[9]*m_p_4x4_data[12] + m_p_4x4_data[2]*m_p_4x4_data[8]*m_p_4x4_data[13] - m_p_4x4_data[0]*m_p_4x4_data[10]*m_p_4x4_data[13] - m_p_4x4_data[1]*m_p_4x4_data[8]*m_p_4x4_data[14] + m_p_4x4_data[0]*m_p_4x4_data[9]*m_p_4x4_data[14]) / matrix_determinant;
472  m14 = (m_p_4x4_data[2]*m_p_4x4_data[5]*m_p_4x4_data[12] - m_p_4x4_data[1]*m_p_4x4_data[6]*m_p_4x4_data[12] - m_p_4x4_data[2]*m_p_4x4_data[4]*m_p_4x4_data[13] + m_p_4x4_data[0]*m_p_4x4_data[6]*m_p_4x4_data[13] + m_p_4x4_data[1]*m_p_4x4_data[4]*m_p_4x4_data[14] - m_p_4x4_data[0]*m_p_4x4_data[5]*m_p_4x4_data[14]) / matrix_determinant;
473  m15 = (m_p_4x4_data[1]*m_p_4x4_data[6]*m_p_4x4_data[8] - m_p_4x4_data[2]*m_p_4x4_data[5]*m_p_4x4_data[8] + m_p_4x4_data[2]*m_p_4x4_data[4]*m_p_4x4_data[9] - m_p_4x4_data[0]*m_p_4x4_data[6]*m_p_4x4_data[9] - m_p_4x4_data[1]*m_p_4x4_data[4]*m_p_4x4_data[10] + m_p_4x4_data[0]*m_p_4x4_data[5]*m_p_4x4_data[10]) / matrix_determinant;
474  }
475 
476  return (Matrix4x4<T>(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15));
477 }
478 
479 
480 //----------------------------------------------------------------------------------
481 template<typename T> Matrix4x4<T>& Matrix4x4<T>::operator=(const Matrix4x4& aMatrix)
482 //----------------------------------------------------------------------------------
483 {
484  memcpy(m_p_4x4_data, aMatrix.m_p_4x4_data, sizeof(m_p_4x4_data));
485 
486  m_small_matrix_up_to_date = false;
487 
488  return (*this);
489 }
490 
491 
492 //--------------------------------------------------------------------------------
493 template<typename T> Vec3<T> Matrix4x4<T>::operator*(const Vec3<T>& aVector) const
494 //--------------------------------------------------------------------------------
495 {
496  T x, y, z, w;
497  x = m_p_4x4_data[0] * aVector.getX() + m_p_4x4_data[4] * aVector.getY() + m_p_4x4_data[8] * aVector.getZ() + m_p_4x4_data[12];
498  y = m_p_4x4_data[1] * aVector.getX() + m_p_4x4_data[5] * aVector.getY() + m_p_4x4_data[9] * aVector.getZ() + m_p_4x4_data[13];
499  z = m_p_4x4_data[2] * aVector.getX() + m_p_4x4_data[6] * aVector.getY() + m_p_4x4_data[10] * aVector.getZ() + m_p_4x4_data[14];
500  w = m_p_4x4_data[3] * aVector.getX() + m_p_4x4_data[7] * aVector.getY() + m_p_4x4_data[11] * aVector.getZ() + m_p_4x4_data[15];
501  return (Vec3<T>(x / w, y / w, z / w));
502 }
503 
504 
505 //------------------------------------------------------------------------------------------
506 template<typename T> Matrix4x4<T> Matrix4x4<T>::operator*(const Matrix4x4<T>& aMatrix) const
507 //------------------------------------------------------------------------------------------
508 {
509  Matrix4x4<T> result;
510 
511  T* p_matrix1(const_cast<T*>(aMatrix.m_p_4x4_data));
512  T* p_result(result.m_p_4x4_data);
513 
514  // Process each column
515  for (int i(0); i < 4; i++, p_matrix1 += 4)
516  {
517  T* p_matrix0(const_cast<T*>(m_p_4x4_data));
518 
519  // Process each line
520  for (int j(0); j < 4; j++, p_matrix0++, p_result++)
521  {
522  T* p_temp(p_matrix1);
523 
524  *p_result = p_matrix0[0] * *p_temp++;
525  *p_result += p_matrix0[4] * *p_temp++;
526  *p_result += p_matrix0[8] * *p_temp++;
527  *p_result += p_matrix0[12] * *p_temp++;
528  }
529  }
530 
531  return (result);
532 }
533 
534 
535 //--------------------------------------------------------------------------------------
536 template<typename T> Matrix4x4<T>& Matrix4x4<T>::operator*=(const Matrix4x4<T>& aMatrix)
537 //--------------------------------------------------------------------------------------
538 {
539  *this = *this * aMatrix;
540 
541  m_small_matrix_up_to_date = false;
542 
543  return (*this);
544 }
545 
546 
547 //-----------------------------------------------------
548 template<typename T> const T* Matrix4x4<T>::get() const
549 //-----------------------------------------------------
550 {
551  return (&m_p_4x4_data[0]);
552 }
553 
554 
555 //--------------------------------------------------------
556 template<typename T> const T* Matrix4x4<T>::get4x4() const
557 //--------------------------------------------------------
558 {
559  return (&m_p_4x4_data[0]);
560 }
561 
562 
563 //--------------------------------------------------
564 template<typename T> const T* Matrix4x4<T>::get3x3()
565 //--------------------------------------------------
566 {
567  // The 4x4 matrix has changed, the 3x3 matrix needs to be updated
568  if (!m_small_matrix_up_to_date)
569  {
570  m_p_3x3_data[0] = m_p_4x4_data[ 0];
571  m_p_3x3_data[1] = m_p_4x4_data[ 1];
572  m_p_3x3_data[2] = m_p_4x4_data[ 2];
573 
574  m_p_3x3_data[3] = m_p_4x4_data[ 4];
575  m_p_3x3_data[4] = m_p_4x4_data[ 5];
576  m_p_3x3_data[5] = m_p_4x4_data[ 6];
577 
578  m_p_3x3_data[6] = m_p_4x4_data[ 8];
579  m_p_3x3_data[7] = m_p_4x4_data[ 9];
580  m_p_3x3_data[8] = m_p_4x4_data[10];
581 
582  m_small_matrix_up_to_date = true;
583  }
584 
585  return (&m_p_3x3_data[0]);
586 }
587 
588 
589 //------------------------------------------------------------------------
590 template<typename T> std::vector<double> Matrix4x4<T>::getAsVector() const
591 //------------------------------------------------------------------------
592 {
593  std::vector<double> temp;
594 
595  for (unsigned int i = 0; i < 16; ++i)
596  {
597  temp.push_back(m_p_4x4_data[i]);
598  }
599 
600  return (temp);
601 }
602 
603 
604 //---------------------------------------------------
605 template<typename T> void Matrix4x4<T>::print() const
606 //---------------------------------------------------
607 {
608  print(std::cout);
609 }
610 
611 
612 //-------------------------------------------------------------------------------
613 template<typename T> void Matrix4x4<T>::print(std::ostream& anOutputStream) const
614 //-------------------------------------------------------------------------------
615 {
616  anOutputStream << m_p_4x4_data[0] << " " << m_p_4x4_data[4] << " " << m_p_4x4_data[ 8] << " " << m_p_4x4_data[12] << std::endl;
617  anOutputStream << m_p_4x4_data[1] << " " << m_p_4x4_data[5] << " " << m_p_4x4_data[ 9] << " " << m_p_4x4_data[13] << std::endl;
618  anOutputStream << m_p_4x4_data[2] << " " << m_p_4x4_data[6] << " " << m_p_4x4_data[10] << " " << m_p_4x4_data[14] << std::endl;
619  anOutputStream << m_p_4x4_data[3] << " " << m_p_4x4_data[7] << " " << m_p_4x4_data[11] << " " << m_p_4x4_data[15] << std::endl;
620 }
621 
622 
623 //--------------------------------------------------------------------------
624 template <typename T> std::ostream& operator<<(std::ostream& anOutputStream,
625  const Matrix4x4<T>& aMatrix)
626 //--------------------------------------------------------------------------
627 {
628  aMatrix.print(anOutputStream);
629  return (anOutputStream);
630 }
631 
632 
633 } // namespace gVirtualXRay
const double m2
square meter
Definition: Units.h:113
T m_p_4x4_data[4 *4]
the matrix data
Definition: Matrix4x4.h:464
double length() const
Get the length of the vector.
Definition: Vec3.inl:139
Matrix4x4(const T &a1=1.0f, const T &a2=0.0f, const T &a3=0.0f, const T &a4=0.0f, const T &a5=0.0f, const T &a6=1.0f, const T &a7=0.0f, const T &a8=0.0f, const T &a9=0.0f, const T &a10=0.0f, const T &a11=1.0f, const T &a12=0.0f, const T &a13=0.0f, const T &a14=0.0f, const T &a15=0.0f, const T &a16=1.0f)
Default Constructor (create an identity matrix).
Definition: Matrix4x4.inl:87
Vec3 is a template class to handle a 3D vector.
Definition: Vec3.h:88
T getX() const
Accessor on the position along the x-axis.
Definition: Vec3.inl:115
T getZ() const
Accessor on the position along the z-axis.
Definition: Vec3.inl:131
Exception is a class to handle exceptions.
Definition: Exception.h:109
Vec3 normal() const
Get the unit vector corresponding to the normed current vector.
Definition: Vec3.inl:147
Generic class to handle exceptions.
T getY() const
Accessor on the position along the y-axis.
Definition: Vec3.inl:123
void print() const
Print the matrix in the console.
Definition: Matrix4x4.inl:605
std::ostream & operator<<(std::ostream &anOutputSream, const gVirtualXRay::AtomicElement &anElement)
operator <<
const double Pi
Pi.
Constant values, such as the Z number of different atoms, etc.
Matrix4x4 is a template class to handle a 4 by 4 matrix.
Definition: Matrix4x4.h:89
Image< T > operator*(const T &aValue, const Image< T > &anImage)
Definition: Image.inl:5104
const double m3
cubic meter
Definition: Units.h:122