libmoldeo (Moldeo 1.0 Core)
1.0
libmoldeo es el conjunto de objetos y funciones, que permiten ejecutar las operaciones básicas de la plataforma Moldeo, y que compone su núcleo.
Página principal
Páginas relacionadas
Módulos
Namespaces
Clases
Archivos
Lista de archivos
Miembros de los ficheros
Todo
Clases
Namespaces
Archivos
Funciones
Variables
'typedefs'
Enumeraciones
Valores de enumeraciones
Amigas
'defines'
Grupos
Páginas
moMathMatrix.cpp
Ir a la documentación de este archivo.
1
/*******************************************************************************
2
3
moMathMatrix.h
4
5
****************************************************************************
6
* *
7
* This source is free software; you can redistribute it and/or modify *
8
* it under the terms of the GNU General Public License as published by *
9
* the Free Software Foundation; either version 2 of the License, or *
10
* (at your option) any later version. *
11
* *
12
* This code is distributed in the hope that it will be useful, but *
13
* WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15
* General Public License for more details. *
16
* *
17
* A copy of the GNU General Public License is available on the World *
18
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
19
* obtain it by writing to the Free Software Foundation, *
20
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21
* *
22
****************************************************************************
23
24
Copyright(C) 2006 Fabricio Costa
25
26
Authors:
27
Fabricio Costa
28
Andrés Colubri
29
30
Portions taken from
31
Wild Magic Source Code
32
David Eberly
33
http://www.geometrictools.com
34
Copyright (c) 1998-2007
35
36
*******************************************************************************/
37
38
#include "
moMathMatrix.h
"
39
40
#include <
moArray.h
>
41
moDefineDynamicArray
( moMatrix2fArray )
42
moDefineDynamicArray
( moMatrix2dArray )
43
moDefineDynamicArray
( moMatrix3fArray )
44
moDefineDynamicArray
( moMatrix3dArray )
45
moDefineDynamicArray
( moMatrix4fArray )
46
moDefineDynamicArray
( moMatrix4dArray )
47
48
// momoMatrix2 class ------------------------------------------------------------
49
/*
50
template <class Real>
51
moMatrix2<Real>::moMatrix2 (bool bZero)
52
{
53
if (bZero)
54
{
55
MakeZero();
56
}
57
else
58
{
59
MakeIdentity();
60
}
61
}
62
63
template <class Real>
64
moMatrix2<Real>::moMatrix2 (const moMatrix2& rkM) : moAbstract(rkM)
65
{
66
m_bInitialized = rkM.m_bInitialized;
67
m_afEntry[0] = rkM.m_afEntry[0];
68
m_afEntry[1] = rkM.m_afEntry[1];
69
m_afEntry[2] = rkM.m_afEntry[2];
70
m_afEntry[3] = rkM.m_afEntry[3];
71
}
72
73
template <class Real>
74
moMatrix2<Real>::moMatrix2 (Real fM00, Real fM01, Real fM10, Real fM11)
75
{
76
m_afEntry[0] = fM00;
77
m_afEntry[1] = fM01;
78
m_afEntry[2] = fM10;
79
m_afEntry[3] = fM11;
80
}
81
82
template <class Real>
83
moMatrix2<Real>::moMatrix2 (const Real afEntry[4], bool bRowMajor)
84
{
85
if (bRowMajor)
86
{
87
m_afEntry[0] = afEntry[0];
88
m_afEntry[1] = afEntry[1];
89
m_afEntry[2] = afEntry[2];
90
m_afEntry[3] = afEntry[3];
91
}
92
else
93
{
94
m_afEntry[0] = afEntry[0];
95
m_afEntry[1] = afEntry[2];
96
m_afEntry[2] = afEntry[1];
97
m_afEntry[3] = afEntry[3];
98
}
99
}
100
101
template <class Real>
102
moMatrix2<Real>::moMatrix2 (const moVector2<Real>& rkU, const moVector2<Real>& rkV,
103
bool bColumns)
104
{
105
if (bColumns)
106
{
107
m_afEntry[0] = rkU[0];
108
m_afEntry[1] = rkV[0];
109
m_afEntry[2] = rkU[1];
110
m_afEntry[3] = rkV[1];
111
}
112
else
113
{
114
m_afEntry[0] = rkU[0];
115
m_afEntry[1] = rkU[1];
116
m_afEntry[2] = rkV[0];
117
m_afEntry[3] = rkV[1];
118
}
119
}
120
121
template <class Real>
122
moMatrix2<Real>::moMatrix2 (const moVector2<Real>* akV, bool bColumns)
123
{
124
if (bColumns)
125
{
126
m_afEntry[0] = akV[0][0];
127
m_afEntry[1] = akV[1][0];
128
m_afEntry[2] = akV[0][1];
129
m_afEntry[3] = akV[1][1];
130
}
131
else
132
{
133
m_afEntry[0] = akV[0][0];
134
m_afEntry[1] = akV[0][1];
135
m_afEntry[2] = akV[1][0];
136
m_afEntry[3] = akV[1][1];
137
}
138
}
139
140
template <class Real>
141
moMatrix2<Real>::moMatrix2 (Real fM00, Real fM11)
142
{
143
MakeDiagonal(fM00,fM11);
144
}
145
146
template <class Real>
147
moMatrix2<Real>::moMatrix2 (Real fAngle)
148
{
149
FromAngle(fAngle);
150
}
151
152
template <class Real>
153
moMatrix2<Real>::moMatrix2 (const moVector2<Real>& rkU, const moVector2<Real>& rkV)
154
{
155
MakeTensorProduct(rkU,rkV);
156
}
157
158
template <class Real>
159
void moMatrix2<Real>::MakeZero ()
160
{
161
m_afEntry[0] = (Real)0.0;
162
m_afEntry[1] = (Real)0.0;
163
m_afEntry[2] = (Real)0.0;
164
m_afEntry[3] = (Real)0.0;
165
}
166
167
template <class Real>
168
void moMatrix2<Real>::MakeIdentity ()
169
{
170
m_afEntry[0] = (Real)1.0;
171
m_afEntry[1] = (Real)0.0;
172
m_afEntry[2] = (Real)0.0;
173
m_afEntry[3] = (Real)1.0;
174
}
175
176
template <class Real>
177
void moMatrix2<Real>::MakeDiagonal (Real fM00, Real fM11)
178
{
179
m_afEntry[0] = fM00;
180
m_afEntry[1] = (Real)0.0;
181
m_afEntry[2] = (Real)0.0;
182
m_afEntry[3] = fM11;
183
}
184
185
template <class Real>
186
void moMatrix2<Real>::FromAngle (Real fAngle)
187
{
188
m_afEntry[0] = moMath<Real>::Cos(fAngle);
189
m_afEntry[2] = moMath<Real>::Sin(fAngle);
190
m_afEntry[1] = -m_afEntry[2];
191
m_afEntry[3] = m_afEntry[0];
192
}
193
194
template <class Real>
195
void moMatrix2<Real>::MakeTensorProduct (const moVector2<Real>& rkU,
196
const moVector2<Real>& rkV)
197
{
198
m_afEntry[0] = rkU[0]*rkV[0];
199
m_afEntry[1] = rkU[0]*rkV[1];
200
m_afEntry[2] = rkU[1]*rkV[0];
201
m_afEntry[3] = rkU[1]*rkV[1];
202
}
203
204
template <class Real>
205
void moMatrix2<Real>::SetRow (int iRow, const moVector2<Real>& rkV)
206
{
207
int i0 = 2*iRow ,i1 = i0+1;
208
m_afEntry[i0] = rkV[0];
209
m_afEntry[i1] = rkV[1];
210
}
211
212
template <class Real>
213
moVector2<Real> moMatrix2<Real>::GetRow (int iRow) const
214
{
215
int i0 = 2*iRow ,i1 = i0+1;
216
return moVector2<Real>(m_afEntry[i0],m_afEntry[i1]);
217
}
218
219
template <class Real>
220
void moMatrix2<Real>::SetColumn (int iCol, const moVector2<Real>& rkV)
221
{
222
m_afEntry[iCol] = rkV[0];
223
m_afEntry[iCol+2] = rkV[1];
224
}
225
226
template <class Real>
227
moVector2<Real> moMatrix2<Real>::GetColumn (int iCol) const
228
{
229
return moVector2<Real>(m_afEntry[iCol],m_afEntry[iCol+2]);
230
}
231
232
template <class Real>
233
void moMatrix2<Real>::GetColumnMajor (Real* afCMajor) const
234
{
235
afCMajor[0] = m_afEntry[0];
236
afCMajor[1] = m_afEntry[2];
237
afCMajor[2] = m_afEntry[1];
238
afCMajor[3] = m_afEntry[3];
239
}
240
241
template <class Real>
242
int moMatrix2<Real>::CompareArrays (const moMatrix2& rkM) const
243
{
244
return memcmp(m_afEntry,rkM.m_afEntry,4*sizeof(Real));
245
}
246
247
template <class Real>
248
bool moMatrix2<Real>::operator== (const moMatrix2& rkM) const
249
{
250
return CompareArrays(rkM) == 0;
251
}
252
253
template <class Real>
254
bool moMatrix2<Real>::operator!= (const moMatrix2& rkM) const
255
{
256
return CompareArrays(rkM) != 0;
257
}
258
259
template <class Real>
260
bool moMatrix2<Real>::operator< (const moMatrix2& rkM) const
261
{
262
return CompareArrays(rkM) < 0;
263
}
264
265
template <class Real>
266
bool moMatrix2<Real>::operator<= (const moMatrix2& rkM) const
267
{
268
return CompareArrays(rkM) <= 0;
269
}
270
271
template <class Real>
272
bool moMatrix2<Real>::operator> (const moMatrix2& rkM) const
273
{
274
return CompareArrays(rkM) > 0;
275
}
276
277
template <class Real>
278
bool moMatrix2<Real>::operator>= (const moMatrix2& rkM) const
279
{
280
return CompareArrays(rkM) >= 0;
281
}
282
283
template <class Real>
284
moMatrix2<Real> moMatrix2<Real>::Transpose () const
285
{
286
return moMatrix2<Real>(
287
m_afEntry[0],
288
m_afEntry[2],
289
m_afEntry[1],
290
m_afEntry[3]);
291
}
292
293
template <class Real>
294
moMatrix2<Real> moMatrix2<Real>::TransposeTimes (const moMatrix2& rkM) const
295
{
296
// P = A^T*B
297
return moMatrix2<Real>(
298
m_afEntry[0]*rkM.m_afEntry[0] + m_afEntry[2]*rkM.m_afEntry[2],
299
m_afEntry[0]*rkM.m_afEntry[1] + m_afEntry[2]*rkM.m_afEntry[3],
300
m_afEntry[1]*rkM.m_afEntry[0] + m_afEntry[3]*rkM.m_afEntry[2],
301
m_afEntry[1]*rkM.m_afEntry[1] + m_afEntry[3]*rkM.m_afEntry[3]);
302
}
303
304
template <class Real>
305
moMatrix2<Real> moMatrix2<Real>::TimesTranspose (const moMatrix2& rkM) const
306
{
307
// P = A*B^T
308
return moMatrix2<Real>(
309
m_afEntry[0]*rkM.m_afEntry[0] + m_afEntry[1]*rkM.m_afEntry[1],
310
m_afEntry[0]*rkM.m_afEntry[2] + m_afEntry[1]*rkM.m_afEntry[3],
311
m_afEntry[2]*rkM.m_afEntry[0] + m_afEntry[3]*rkM.m_afEntry[1],
312
m_afEntry[2]*rkM.m_afEntry[2] + m_afEntry[3]*rkM.m_afEntry[3]);
313
}
314
315
template <class Real>
316
moMatrix2<Real> moMatrix2<Real>::Inverse () const
317
{
318
moMatrix2<Real> kInverse;
319
320
Real fDet = m_afEntry[0]*m_afEntry[3] - m_afEntry[1]*m_afEntry[2];
321
if (moMath<Real>::FAbs(fDet) > moMath<Real>::ZERO_TOLERANCE)
322
{
323
Real fInvDet = ((Real)1.0)/fDet;
324
kInverse.m_afEntry[0] = m_afEntry[3]*fInvDet;
325
kInverse.m_afEntry[1] = -m_afEntry[1]*fInvDet;
326
kInverse.m_afEntry[2] = -m_afEntry[2]*fInvDet;
327
kInverse.m_afEntry[3] = m_afEntry[0]*fInvDet;
328
}
329
else
330
{
331
kInverse.m_afEntry[0] = (Real)0.0;
332
kInverse.m_afEntry[1] = (Real)0.0;
333
kInverse.m_afEntry[2] = (Real)0.0;
334
kInverse.m_afEntry[3] = (Real)0.0;
335
}
336
337
return kInverse;
338
}
339
340
template <class Real>
341
moMatrix2<Real> moMatrix2<Real>::Adjoint () const
342
{
343
return moMatrix2<Real>(
344
m_afEntry[3],
345
-m_afEntry[1],
346
-m_afEntry[2],
347
m_afEntry[0]);
348
}
349
350
template <class Real>
351
Real moMatrix2<Real>::Determinant () const
352
{
353
return m_afEntry[0]*m_afEntry[3] - m_afEntry[1]*m_afEntry[2];
354
}
355
356
template <class Real>
357
Real moMatrix2<Real>::QForm (const moVector2<Real>& rkU,
358
const moVector2<Real>& rkV) const
359
{
360
return rkU.Dot((*this)*rkV);
361
}
362
363
template <class Real>
364
void moMatrix2<Real>::ToAngle (Real& rfAngle) const
365
{
366
// assert: matrix is a rotation
367
rfAngle = moMath<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
368
}
369
370
template <class Real>
371
void moMatrix2<Real>::Orthonormalize ()
372
{
373
// Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is
374
// M = [m0|m1], then orthonormal output matrix is Q = [q0|q1],
375
//
376
// q0 = m0/|m0|
377
// q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
378
//
379
// where |V| indicates length of vector V and A*B indicates dot
380
// product of vectors A and B.
381
382
// compute q0
383
Real fInvLength = moMath<Real>::InvSqrt(m_afEntry[0]*m_afEntry[0] +
384
m_afEntry[2]*m_afEntry[2]);
385
386
m_afEntry[0] *= fInvLength;
387
m_afEntry[2] *= fInvLength;
388
389
// compute q1
390
Real fDot0 = m_afEntry[0]*m_afEntry[1] + m_afEntry[2]*m_afEntry[3];
391
m_afEntry[1] -= fDot0*m_afEntry[0];
392
m_afEntry[3] -= fDot0*m_afEntry[2];
393
394
fInvLength = moMath<Real>::InvSqrt(m_afEntry[1]*m_afEntry[1] +
395
m_afEntry[3]*m_afEntry[3]);
396
397
m_afEntry[1] *= fInvLength;
398
m_afEntry[3] *= fInvLength;
399
}
400
401
template <class Real>
402
void moMatrix2<Real>::EigenDecomposition (moMatrix2& rkRot, moMatrix2& rkDiag) const
403
{
404
Real fTrace = m_afEntry[0] + m_afEntry[3];
405
Real fDiff = m_afEntry[0] - m_afEntry[3];
406
Real fDiscr = moMath<Real>::Sqrt(fDiff*fDiff +
407
((Real)4.0)*m_afEntry[1]*m_afEntry[1]);
408
Real fEVal0 = ((Real)0.5)*(fTrace-fDiscr);
409
Real fEVal1 = ((Real)0.5)*(fTrace+fDiscr);
410
rkDiag.MakeDiagonal(fEVal0,fEVal1);
411
412
Real fCos, fSin;
413
if (fDiff >= (Real)0.0)
414
{
415
fCos = m_afEntry[1];
416
fSin = fEVal0 - m_afEntry[0];
417
}
418
else
419
{
420
fCos = fEVal0 - m_afEntry[3];
421
fSin = m_afEntry[1];
422
}
423
Real fTmp = moMath<Real>::InvSqrt(fCos*fCos + fSin*fSin);
424
fCos *= fTmp;
425
fSin *= fTmp;
426
427
rkRot.m_afEntry[0] = fCos;
428
rkRot.m_afEntry[1] = -fSin;
429
rkRot.m_afEntry[2] = fSin;
430
rkRot.m_afEntry[3] = fCos;
431
}
432
*/
433
434
template<>
const
moMatrix2
<
MOfloat
>
moMatrix2
<
MOfloat
>::ZERO(
435
0.0
f
,0.0f,
436
0.0f,0.0f);
437
template<>
const
moMatrix2
<
MOfloat
>
moMatrix2
<
MOfloat
>::IDENTITY(
438
1.0f,0.0f,
439
0.0f,1.0f);
440
441
template<>
const
moMatrix2
<
MOdouble
>
moMatrix2
<
MOdouble
>::ZERO(
442
0.0,0.0,
443
0.0,0.0);
444
template<>
const
moMatrix2
<
MOdouble
>
moMatrix2
<
MOdouble
>::IDENTITY(
445
1.0,0.0,
446
0.0,1.0);
447
448
// momoMatrix3 class ------------------------------------------------------------
449
/*
450
template <class Real>
451
moMatrix3<Real>::moMatrix3 (bool bZero)
452
{
453
if (bZero)
454
{
455
MakeZero();
456
}
457
else
458
{
459
MakeIdentity();
460
}
461
}
462
463
template <class Real>
464
moMatrix3<Real>::moMatrix3 (const moMatrix3& rkM) : moAbstract(rkM)
465
{
466
m_afEntry[0] = rkM.m_afEntry[0];
467
m_afEntry[1] = rkM.m_afEntry[1];
468
m_afEntry[2] = rkM.m_afEntry[2];
469
m_afEntry[3] = rkM.m_afEntry[3];
470
m_afEntry[4] = rkM.m_afEntry[4];
471
m_afEntry[5] = rkM.m_afEntry[5];
472
m_afEntry[6] = rkM.m_afEntry[6];
473
m_afEntry[7] = rkM.m_afEntry[7];
474
m_afEntry[8] = rkM.m_afEntry[8];
475
}
476
477
template <class Real>
478
moMatrix3<Real>::moMatrix3 (Real fM00, Real fM01, Real fM02, Real fM10, Real fM11,
479
Real fM12, Real fM20, Real fM21, Real fM22)
480
{
481
m_afEntry[0] = fM00;
482
m_afEntry[1] = fM01;
483
m_afEntry[2] = fM02;
484
m_afEntry[3] = fM10;
485
m_afEntry[4] = fM11;
486
m_afEntry[5] = fM12;
487
m_afEntry[6] = fM20;
488
m_afEntry[7] = fM21;
489
m_afEntry[8] = fM22;
490
}
491
492
template <class Real>
493
moMatrix3<Real>::moMatrix3 (const Real afEntry[9], bool bRowMajor)
494
{
495
if (bRowMajor)
496
{
497
m_afEntry[0] = afEntry[0];
498
m_afEntry[1] = afEntry[1];
499
m_afEntry[2] = afEntry[2];
500
m_afEntry[3] = afEntry[3];
501
m_afEntry[4] = afEntry[4];
502
m_afEntry[5] = afEntry[5];
503
m_afEntry[6] = afEntry[6];
504
m_afEntry[7] = afEntry[7];
505
m_afEntry[8] = afEntry[8];
506
}
507
else
508
{
509
m_afEntry[0] = afEntry[0];
510
m_afEntry[1] = afEntry[3];
511
m_afEntry[2] = afEntry[6];
512
m_afEntry[3] = afEntry[1];
513
m_afEntry[4] = afEntry[4];
514
m_afEntry[5] = afEntry[7];
515
m_afEntry[6] = afEntry[2];
516
m_afEntry[7] = afEntry[5];
517
m_afEntry[8] = afEntry[8];
518
}
519
}
520
521
template <class Real>
522
moMatrix3<Real>::moMatrix3 (const moVector3<Real>& rkU, const moVector3<Real>& rkV,
523
const moVector3<Real>& rkW, bool bColumns)
524
{
525
if (bColumns)
526
{
527
m_afEntry[0] = rkU[0];
528
m_afEntry[1] = rkV[0];
529
m_afEntry[2] = rkW[0];
530
m_afEntry[3] = rkU[1];
531
m_afEntry[4] = rkV[1];
532
m_afEntry[5] = rkW[1];
533
m_afEntry[6] = rkU[2];
534
m_afEntry[7] = rkV[2];
535
m_afEntry[8] = rkW[2];
536
}
537
else
538
{
539
m_afEntry[0] = rkU[0];
540
m_afEntry[1] = rkU[1];
541
m_afEntry[2] = rkU[2];
542
m_afEntry[3] = rkV[0];
543
m_afEntry[4] = rkV[1];
544
m_afEntry[5] = rkV[2];
545
m_afEntry[6] = rkW[0];
546
m_afEntry[7] = rkW[1];
547
m_afEntry[8] = rkW[2];
548
}
549
}
550
551
template <class Real>
552
moMatrix3<Real>::moMatrix3 (const moVector3<Real>* akV, bool bColumns)
553
{
554
if (bColumns)
555
{
556
m_afEntry[0] = akV[0][0];
557
m_afEntry[1] = akV[1][0];
558
m_afEntry[2] = akV[2][0];
559
m_afEntry[3] = akV[0][1];
560
m_afEntry[4] = akV[1][1];
561
m_afEntry[5] = akV[2][1];
562
m_afEntry[6] = akV[0][2];
563
m_afEntry[7] = akV[1][2];
564
m_afEntry[8] = akV[2][2];
565
}
566
else
567
{
568
m_afEntry[0] = akV[0][0];
569
m_afEntry[1] = akV[0][1];
570
m_afEntry[2] = akV[0][2];
571
m_afEntry[3] = akV[1][0];
572
m_afEntry[4] = akV[1][1];
573
m_afEntry[5] = akV[1][2];
574
m_afEntry[6] = akV[2][0];
575
m_afEntry[7] = akV[2][1];
576
m_afEntry[8] = akV[2][2];
577
}
578
}
579
580
template <class Real>
581
moMatrix3<Real>::moMatrix3 (Real fM00, Real fM11, Real fM22)
582
{
583
MakeDiagonal(fM00,fM11,fM22);
584
}
585
586
template <class Real>
587
moMatrix3<Real>::moMatrix3 (const moVector3<Real>& rkAxis, Real fAngle)
588
{
589
FromAxisAngle(rkAxis,fAngle);
590
}
591
592
template <class Real>
593
moMatrix3<Real>::moMatrix3 (const moVector3<Real>& rkU, const moVector3<Real>& rkV)
594
{
595
MakeTensorProduct(rkU,rkV);
596
}
597
598
template <class Real>
599
moMatrix3<Real>& moMatrix3<Real>::MakeZero ()
600
{
601
m_afEntry[0] = (Real)0.0;
602
m_afEntry[1] = (Real)0.0;
603
m_afEntry[2] = (Real)0.0;
604
m_afEntry[3] = (Real)0.0;
605
m_afEntry[4] = (Real)0.0;
606
m_afEntry[5] = (Real)0.0;
607
m_afEntry[6] = (Real)0.0;
608
m_afEntry[7] = (Real)0.0;
609
m_afEntry[8] = (Real)0.0;
610
return *this;
611
}
612
613
template <class Real>
614
moMatrix3<Real>& moMatrix3<Real>::MakeIdentity ()
615
{
616
m_afEntry[0] = (Real)1.0;
617
m_afEntry[1] = (Real)0.0;
618
m_afEntry[2] = (Real)0.0;
619
m_afEntry[3] = (Real)0.0;
620
m_afEntry[4] = (Real)1.0;
621
m_afEntry[5] = (Real)0.0;
622
m_afEntry[6] = (Real)0.0;
623
m_afEntry[7] = (Real)0.0;
624
m_afEntry[8] = (Real)1.0;
625
return *this;
626
}
627
628
template <class Real>
629
moMatrix3<Real>& moMatrix3<Real>::MakeDiagonal (Real fM00, Real fM11, Real fM22)
630
{
631
m_afEntry[0] = fM00;
632
m_afEntry[1] = (Real)0.0;
633
m_afEntry[2] = (Real)0.0;
634
m_afEntry[3] = (Real)0.0;
635
m_afEntry[4] = fM11;
636
m_afEntry[5] = (Real)0.0;
637
m_afEntry[6] = (Real)0.0;
638
m_afEntry[7] = (Real)0.0;
639
m_afEntry[8] = fM22;
640
return *this;
641
}
642
643
template <class Real>
644
moMatrix3<Real>& moMatrix3<Real>::FromAxisAngle (const moVector3<Real>& rkAxis,
645
Real fAngle)
646
{
647
Real fCos = moMath<Real>::Cos(fAngle);
648
Real fSin = moMath<Real>::Sin(fAngle);
649
Real fOneMinusCos = ((Real)1.0)-fCos;
650
Real fX2 = rkAxis[0]*rkAxis[0];
651
Real fY2 = rkAxis[1]*rkAxis[1];
652
Real fZ2 = rkAxis[2]*rkAxis[2];
653
Real fXYM = rkAxis[0]*rkAxis[1]*fOneMinusCos;
654
Real fXZM = rkAxis[0]*rkAxis[2]*fOneMinusCos;
655
Real fYZM = rkAxis[1]*rkAxis[2]*fOneMinusCos;
656
Real fXSin = rkAxis[0]*fSin;
657
Real fYSin = rkAxis[1]*fSin;
658
Real fZSin = rkAxis[2]*fSin;
659
660
m_afEntry[0] = fX2*fOneMinusCos+fCos;
661
m_afEntry[1] = fXYM-fZSin;
662
m_afEntry[2] = fXZM+fYSin;
663
m_afEntry[3] = fXYM+fZSin;
664
m_afEntry[4] = fY2*fOneMinusCos+fCos;
665
m_afEntry[5] = fYZM-fXSin;
666
m_afEntry[6] = fXZM-fYSin;
667
m_afEntry[7] = fYZM+fXSin;
668
m_afEntry[8] = fZ2*fOneMinusCos+fCos;
669
670
return *this;
671
}
672
673
template <class Real>
674
moMatrix3<Real>& moMatrix3<Real>::MakeTensorProduct (const moVector3<Real>& rkU,
675
const moVector3<Real>& rkV)
676
{
677
m_afEntry[0] = rkU[0]*rkV[0];
678
m_afEntry[1] = rkU[0]*rkV[1];
679
m_afEntry[2] = rkU[0]*rkV[2];
680
m_afEntry[3] = rkU[1]*rkV[0];
681
m_afEntry[4] = rkU[1]*rkV[1];
682
m_afEntry[5] = rkU[1]*rkV[2];
683
m_afEntry[6] = rkU[2]*rkV[0];
684
m_afEntry[7] = rkU[2]*rkV[1];
685
m_afEntry[8] = rkU[2]*rkV[2];
686
return *this;
687
}
688
689
template <class Real>
690
void moMatrix3<Real>::SetRow (int iRow, const moVector3<Real>& rkV)
691
{
692
int i0 = 3*iRow, i1 = i0+1, i2 = i1+1;
693
m_afEntry[i0] = rkV[0];
694
m_afEntry[i1] = rkV[1];
695
m_afEntry[i2] = rkV[2];
696
}
697
698
template <class Real>
699
moVector3<Real> moMatrix3<Real>::GetRow (int iRow) const
700
{
701
int i0 = 3*iRow, i1 = i0+1, i2 = i1+1;
702
return moVector3<Real>(m_afEntry[i0],m_afEntry[i1],m_afEntry[i2]);
703
}
704
705
template <class Real>
706
void moMatrix3<Real>::SetColumn (int iCol, const moVector3<Real>& rkV)
707
{
708
m_afEntry[iCol] = rkV[0];
709
m_afEntry[iCol+3] = rkV[1];
710
m_afEntry[iCol+6] = rkV[2];
711
}
712
713
template <class Real>
714
moVector3<Real> moMatrix3<Real>::GetColumn (int iCol) const
715
{
716
return moVector3<Real>(m_afEntry[iCol],m_afEntry[iCol+3],m_afEntry[iCol+6]);
717
}
718
719
template <class Real>
720
void moMatrix3<Real>::GetColumnMajor (Real* afCMajor) const
721
{
722
afCMajor[0] = m_afEntry[0];
723
afCMajor[1] = m_afEntry[3];
724
afCMajor[2] = m_afEntry[6];
725
afCMajor[3] = m_afEntry[1];
726
afCMajor[4] = m_afEntry[4];
727
afCMajor[5] = m_afEntry[7];
728
afCMajor[6] = m_afEntry[2];
729
afCMajor[7] = m_afEntry[5];
730
afCMajor[8] = m_afEntry[8];
731
}
732
733
template <class Real>
734
int moMatrix3<Real>::CompareArrays (const moMatrix3& rkM) const
735
{
736
return memcmp(m_afEntry,rkM.m_afEntry,9*sizeof(Real));
737
}
738
739
template <class Real>
740
bool moMatrix3<Real>::operator== (const moMatrix3& rkM) const
741
{
742
return CompareArrays(rkM) == 0;
743
}
744
745
template <class Real>
746
bool moMatrix3<Real>::operator!= (const moMatrix3& rkM) const
747
{
748
return CompareArrays(rkM) != 0;
749
}
750
751
template <class Real>
752
bool moMatrix3<Real>::operator< (const moMatrix3& rkM) const
753
{
754
return CompareArrays(rkM) < 0;
755
}
756
757
template <class Real>
758
bool moMatrix3<Real>::operator<= (const moMatrix3& rkM) const
759
{
760
return CompareArrays(rkM) <= 0;
761
}
762
763
template <class Real>
764
bool moMatrix3<Real>::operator> (const moMatrix3& rkM) const
765
{
766
return CompareArrays(rkM) > 0;
767
}
768
769
template <class Real>
770
bool moMatrix3<Real>::operator>= (const moMatrix3& rkM) const
771
{
772
return CompareArrays(rkM) >= 0;
773
}
774
775
template <class Real>
776
moMatrix3<Real> moMatrix3<Real>::Transpose () const
777
{
778
return moMatrix3<Real>(
779
m_afEntry[0],
780
m_afEntry[3],
781
m_afEntry[6],
782
m_afEntry[1],
783
m_afEntry[4],
784
m_afEntry[7],
785
m_afEntry[2],
786
m_afEntry[5],
787
m_afEntry[8]);
788
}
789
790
template <class Real>
791
moMatrix3<Real> moMatrix3<Real>::TransposeTimes (const moMatrix3& rkM) const
792
{
793
// P = A^T*B
794
return moMatrix3<Real>(
795
m_afEntry[0]*rkM.m_afEntry[0] +
796
m_afEntry[3]*rkM.m_afEntry[3] +
797
m_afEntry[6]*rkM.m_afEntry[6],
798
799
m_afEntry[0]*rkM.m_afEntry[1] +
800
m_afEntry[3]*rkM.m_afEntry[4] +
801
m_afEntry[6]*rkM.m_afEntry[7],
802
803
m_afEntry[0]*rkM.m_afEntry[2] +
804
m_afEntry[3]*rkM.m_afEntry[5] +
805
m_afEntry[6]*rkM.m_afEntry[8],
806
807
m_afEntry[1]*rkM.m_afEntry[0] +
808
m_afEntry[4]*rkM.m_afEntry[3] +
809
m_afEntry[7]*rkM.m_afEntry[6],
810
811
m_afEntry[1]*rkM.m_afEntry[1] +
812
m_afEntry[4]*rkM.m_afEntry[4] +
813
m_afEntry[7]*rkM.m_afEntry[7],
814
815
m_afEntry[1]*rkM.m_afEntry[2] +
816
m_afEntry[4]*rkM.m_afEntry[5] +
817
m_afEntry[7]*rkM.m_afEntry[8],
818
819
m_afEntry[2]*rkM.m_afEntry[0] +
820
m_afEntry[5]*rkM.m_afEntry[3] +
821
m_afEntry[8]*rkM.m_afEntry[6],
822
823
m_afEntry[2]*rkM.m_afEntry[1] +
824
m_afEntry[5]*rkM.m_afEntry[4] +
825
m_afEntry[8]*rkM.m_afEntry[7],
826
827
m_afEntry[2]*rkM.m_afEntry[2] +
828
m_afEntry[5]*rkM.m_afEntry[5] +
829
m_afEntry[8]*rkM.m_afEntry[8]);
830
}
831
832
template <class Real>
833
moMatrix3<Real> moMatrix3<Real>::TimesTranspose (const moMatrix3& rkM) const
834
{
835
// P = A*B^T
836
return moMatrix3<Real>(
837
m_afEntry[0]*rkM.m_afEntry[0] +
838
m_afEntry[1]*rkM.m_afEntry[1] +
839
m_afEntry[2]*rkM.m_afEntry[2],
840
841
m_afEntry[0]*rkM.m_afEntry[3] +
842
m_afEntry[1]*rkM.m_afEntry[4] +
843
m_afEntry[2]*rkM.m_afEntry[5],
844
845
m_afEntry[0]*rkM.m_afEntry[6] +
846
m_afEntry[1]*rkM.m_afEntry[7] +
847
m_afEntry[2]*rkM.m_afEntry[8],
848
849
m_afEntry[3]*rkM.m_afEntry[0] +
850
m_afEntry[4]*rkM.m_afEntry[1] +
851
m_afEntry[5]*rkM.m_afEntry[2],
852
853
m_afEntry[3]*rkM.m_afEntry[3] +
854
m_afEntry[4]*rkM.m_afEntry[4] +
855
m_afEntry[5]*rkM.m_afEntry[5],
856
857
m_afEntry[3]*rkM.m_afEntry[6] +
858
m_afEntry[4]*rkM.m_afEntry[7] +
859
m_afEntry[5]*rkM.m_afEntry[8],
860
861
m_afEntry[6]*rkM.m_afEntry[0] +
862
m_afEntry[7]*rkM.m_afEntry[1] +
863
m_afEntry[8]*rkM.m_afEntry[2],
864
865
m_afEntry[6]*rkM.m_afEntry[3] +
866
m_afEntry[7]*rkM.m_afEntry[4] +
867
m_afEntry[8]*rkM.m_afEntry[5],
868
869
m_afEntry[6]*rkM.m_afEntry[6] +
870
m_afEntry[7]*rkM.m_afEntry[7] +
871
m_afEntry[8]*rkM.m_afEntry[8]);
872
}
873
874
template <class Real>
875
moMatrix3<Real> moMatrix3<Real>::Inverse () const
876
{
877
// Invert a 3x3 using cofactors. This is faster than using a generic
878
// Gaussian elimination because of the loop overhead of such a method.
879
880
moMatrix3 kInverse;
881
882
kInverse.m_afEntry[0] =
883
m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
884
kInverse.m_afEntry[1] =
885
m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8];
886
kInverse.m_afEntry[2] =
887
m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4];
888
kInverse.m_afEntry[3] =
889
m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
890
kInverse.m_afEntry[4] =
891
m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6];
892
kInverse.m_afEntry[5] =
893
m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5];
894
kInverse.m_afEntry[6] =
895
m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
896
kInverse.m_afEntry[7] =
897
m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7];
898
kInverse.m_afEntry[8] =
899
m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3];
900
901
Real fDet =
902
m_afEntry[0]*kInverse.m_afEntry[0] +
903
m_afEntry[1]*kInverse.m_afEntry[3] +
904
m_afEntry[2]*kInverse.m_afEntry[6];
905
906
if (moMath<Real>::FAbs(fDet) <= moMath<Real>::ZERO_TOLERANCE)
907
{
908
return ZERO;
909
}
910
911
Real fInvDet = ((Real)1.0)/fDet;
912
kInverse.m_afEntry[0] *= fInvDet;
913
kInverse.m_afEntry[1] *= fInvDet;
914
kInverse.m_afEntry[2] *= fInvDet;
915
kInverse.m_afEntry[3] *= fInvDet;
916
kInverse.m_afEntry[4] *= fInvDet;
917
kInverse.m_afEntry[5] *= fInvDet;
918
kInverse.m_afEntry[6] *= fInvDet;
919
kInverse.m_afEntry[7] *= fInvDet;
920
kInverse.m_afEntry[8] *= fInvDet;
921
return kInverse;
922
}
923
924
template <class Real>
925
moMatrix3<Real> moMatrix3<Real>::Adjoint () const
926
{
927
return moMatrix3<Real>(
928
m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7],
929
m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8],
930
m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4],
931
m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8],
932
m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6],
933
m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5],
934
m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6],
935
m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7],
936
m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3]);
937
}
938
939
template <class Real>
940
Real moMatrix3<Real>::Determinant () const
941
{
942
Real fCo00 = m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
943
Real fCo10 = m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
944
Real fCo20 = m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
945
Real fDet = m_afEntry[0]*fCo00 + m_afEntry[1]*fCo10 + m_afEntry[2]*fCo20;
946
return fDet;
947
}
948
949
template <class Real>
950
Real moMatrix3<Real>::QForm (const moVector3<Real>& rkU, const moVector3<Real>& rkV)
951
const
952
{
953
return rkU.Dot((*this)*rkV);
954
}
955
956
template <class Real>
957
moMatrix3<Real> moMatrix3<Real>::TimesDiagonal (const moVector3<Real>& rkDiag) const
958
{
959
return moMatrix3<Real>(
960
m_afEntry[0]*rkDiag[0],m_afEntry[1]*rkDiag[1],m_afEntry[2]*rkDiag[2],
961
m_afEntry[3]*rkDiag[0],m_afEntry[4]*rkDiag[1],m_afEntry[5]*rkDiag[2],
962
m_afEntry[6]*rkDiag[0],m_afEntry[7]*rkDiag[1],m_afEntry[8]*rkDiag[2]);
963
}
964
965
template <class Real>
966
moMatrix3<Real> moMatrix3<Real>::DiagonalTimes (const moVector3<Real>& rkDiag) const
967
{
968
return moMatrix3<Real>(
969
rkDiag[0]*m_afEntry[0],rkDiag[0]*m_afEntry[1],rkDiag[0]*m_afEntry[2],
970
rkDiag[1]*m_afEntry[3],rkDiag[1]*m_afEntry[4],rkDiag[1]*m_afEntry[5],
971
rkDiag[2]*m_afEntry[6],rkDiag[2]*m_afEntry[7],rkDiag[2]*m_afEntry[8]);
972
}
973
974
template <class Real>
975
void moMatrix3<Real>::ToAxisAngle (moVector3<Real>& rkAxis, Real& rfAngle) const
976
{
977
// Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
978
// The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
979
// I is the identity and
980
//
981
// +- -+
982
// P = | 0 -z +y |
983
// | +z 0 -x |
984
// | -y +x 0 |
985
// +- -+
986
//
987
// If A > 0, R represents a counterclockwise rotation about the axis in
988
// the sense of looking from the tip of the axis vector towards the
989
// origin. Some algebra will show that
990
//
991
// cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P
992
//
993
// In the event that A = pi, R-R^t = 0 which prevents us from extracting
994
// the axis through P. Instead note that R = I+2*P^2 when A = pi, so
995
// P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and
996
// z^2-1. We can solve these for axis (x,y,z). Because the angle is pi,
997
// it does not matter which sign you choose on the square roots.
998
999
Real fTrace = m_afEntry[0] + m_afEntry[4] + m_afEntry[8];
1000
Real fCos = ((Real)0.5)*(fTrace-(Real)1.0);
1001
rfAngle = moMath<Real>::ACos(fCos); // in [0,PI]
1002
1003
if (rfAngle > (Real)0.0)
1004
{
1005
if (rfAngle < moMath<Real>::PI)
1006
{
1007
rkAxis[0] = m_afEntry[7]-m_afEntry[5];
1008
rkAxis[1] = m_afEntry[2]-m_afEntry[6];
1009
rkAxis[2] = m_afEntry[3]-m_afEntry[1];
1010
rkAxis.Normalize();
1011
}
1012
else
1013
{
1014
// angle is PI
1015
Real fHalfInverse;
1016
if (m_afEntry[0] >= m_afEntry[4])
1017
{
1018
// r00 >= r11
1019
if (m_afEntry[0] >= m_afEntry[8])
1020
{
1021
// r00 is maximum diagonal term
1022
rkAxis[0] = ((Real)0.5)*moMath<Real>::Sqrt(m_afEntry[0] -
1023
m_afEntry[4] - m_afEntry[8] + (Real)1.0);
1024
fHalfInverse = ((Real)0.5)/rkAxis[0];
1025
rkAxis[1] = fHalfInverse*m_afEntry[1];
1026
rkAxis[2] = fHalfInverse*m_afEntry[2];
1027
}
1028
else
1029
{
1030
// r22 is maximum diagonal term
1031
rkAxis[2] = ((Real)0.5)*moMath<Real>::Sqrt(m_afEntry[8] -
1032
m_afEntry[0] - m_afEntry[4] + (Real)1.0);
1033
fHalfInverse = ((Real)0.5)/rkAxis[2];
1034
rkAxis[0] = fHalfInverse*m_afEntry[2];
1035
rkAxis[1] = fHalfInverse*m_afEntry[5];
1036
}
1037
}
1038
else
1039
{
1040
// r11 > r00
1041
if (m_afEntry[4] >= m_afEntry[8])
1042
{
1043
// r11 is maximum diagonal term
1044
rkAxis[1] = ((Real)0.5)*moMath<Real>::Sqrt(m_afEntry[4] -
1045
m_afEntry[0] - m_afEntry[8] + (Real)1.0);
1046
fHalfInverse = ((Real)0.5)/rkAxis[1];
1047
rkAxis[0] = fHalfInverse*m_afEntry[1];
1048
rkAxis[2] = fHalfInverse*m_afEntry[5];
1049
}
1050
else
1051
{
1052
// r22 is maximum diagonal term
1053
rkAxis[2] = ((Real)0.5)*moMath<Real>::Sqrt(m_afEntry[8] -
1054
m_afEntry[0] - m_afEntry[4] + (Real)1.0);
1055
fHalfInverse = ((Real)0.5)/rkAxis[2];
1056
rkAxis[0] = fHalfInverse*m_afEntry[2];
1057
rkAxis[1] = fHalfInverse*m_afEntry[5];
1058
}
1059
}
1060
}
1061
}
1062
else
1063
{
1064
// The angle is 0 and the matrix is the identity. Any axis will
1065
// work, so just use the x-axis.
1066
rkAxis[0] = (Real)1.0;
1067
rkAxis[1] = (Real)0.0;
1068
rkAxis[2] = (Real)0.0;
1069
}
1070
}
1071
1072
template <class Real>
1073
void moMatrix3<Real>::Orthonormalize ()
1074
{
1075
// Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is
1076
// M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
1077
//
1078
// q0 = m0/|m0|
1079
// q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
1080
// q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
1081
//
1082
// where |V| indicates length of vector V and A*B indicates dot
1083
// product of vectors A and B.
1084
1085
// compute q0
1086
Real fInvLength = moMath<Real>::InvSqrt(m_afEntry[0]*m_afEntry[0] +
1087
m_afEntry[3]*m_afEntry[3] + m_afEntry[6]*m_afEntry[6]);
1088
1089
m_afEntry[0] *= fInvLength;
1090
m_afEntry[3] *= fInvLength;
1091
m_afEntry[6] *= fInvLength;
1092
1093
// compute q1
1094
Real fDot0 = m_afEntry[0]*m_afEntry[1] + m_afEntry[3]*m_afEntry[4] +
1095
m_afEntry[6]*m_afEntry[7];
1096
1097
m_afEntry[1] -= fDot0*m_afEntry[0];
1098
m_afEntry[4] -= fDot0*m_afEntry[3];
1099
m_afEntry[7] -= fDot0*m_afEntry[6];
1100
1101
fInvLength = moMath<Real>::InvSqrt(m_afEntry[1]*m_afEntry[1] +
1102
m_afEntry[4]*m_afEntry[4] + m_afEntry[7]*m_afEntry[7]);
1103
1104
m_afEntry[1] *= fInvLength;
1105
m_afEntry[4] *= fInvLength;
1106
m_afEntry[7] *= fInvLength;
1107
1108
// compute q2
1109
Real fDot1 = m_afEntry[1]*m_afEntry[2] + m_afEntry[4]*m_afEntry[5] +
1110
m_afEntry[7]*m_afEntry[8];
1111
1112
fDot0 = m_afEntry[0]*m_afEntry[2] + m_afEntry[3]*m_afEntry[5] +
1113
m_afEntry[6]*m_afEntry[8];
1114
1115
m_afEntry[2] -= fDot0*m_afEntry[0] + fDot1*m_afEntry[1];
1116
m_afEntry[5] -= fDot0*m_afEntry[3] + fDot1*m_afEntry[4];
1117
m_afEntry[8] -= fDot0*m_afEntry[6] + fDot1*m_afEntry[7];
1118
1119
fInvLength = moMath<Real>::InvSqrt(m_afEntry[2]*m_afEntry[2] +
1120
m_afEntry[5]*m_afEntry[5] + m_afEntry[8]*m_afEntry[8]);
1121
1122
m_afEntry[2] *= fInvLength;
1123
m_afEntry[5] *= fInvLength;
1124
m_afEntry[8] *= fInvLength;
1125
}
1126
1127
template <class Real>
1128
void moMatrix3<Real>::EigenDecomposition (moMatrix3& rkRot, moMatrix3& rkDiag) const
1129
{
1130
// Factor M = R*D*R^T. The columns of R are the eigenvectors. The
1131
// diagonal entries of D are the corresponding eigenvalues.
1132
Real afDiag[3], afSubd[2];
1133
rkRot = *this;
1134
bool bReflection = rkRot.Tridiagonalize(afDiag,afSubd);
1135
bool bConverged = rkRot.QLAlgorithm(afDiag,afSubd);
1136
if (!bConverged) return;
1137
1138
// (insertion) sort eigenvalues in increasing order, d0 <= d1 <= d2
1139
int i;
1140
Real fSave;
1141
1142
if (afDiag[1] < afDiag[0])
1143
{
1144
// swap d0 and d1
1145
fSave = afDiag[0];
1146
afDiag[0] = afDiag[1];
1147
afDiag[1] = fSave;
1148
1149
// swap V0 and V1
1150
for (i = 0; i < 3; i++)
1151
{
1152
fSave = rkRot[i][0];
1153
rkRot[i][0] = rkRot[i][1];
1154
rkRot[i][1] = fSave;
1155
}
1156
bReflection = !bReflection;
1157
}
1158
1159
if (afDiag[2] < afDiag[1])
1160
{
1161
// swap d1 and d2
1162
fSave = afDiag[1];
1163
afDiag[1] = afDiag[2];
1164
afDiag[2] = fSave;
1165
1166
// swap V1 and V2
1167
for (i = 0; i < 3; i++)
1168
{
1169
fSave = rkRot[i][1];
1170
rkRot[i][1] = rkRot[i][2];
1171
rkRot[i][2] = fSave;
1172
}
1173
bReflection = !bReflection;
1174
}
1175
1176
if (afDiag[1] < afDiag[0])
1177
{
1178
// swap d0 and d1
1179
fSave = afDiag[0];
1180
afDiag[0] = afDiag[1];
1181
afDiag[1] = fSave;
1182
1183
// swap V0 and V1
1184
for (i = 0; i < 3; i++)
1185
{
1186
fSave = rkRot[i][0];
1187
rkRot[i][0] = rkRot[i][1];
1188
rkRot[i][1] = fSave;
1189
}
1190
bReflection = !bReflection;
1191
}
1192
1193
rkDiag.MakeDiagonal(afDiag[0],afDiag[1],afDiag[2]);
1194
1195
if (bReflection)
1196
{
1197
// The orthogonal transformation that diagonalizes M is a reflection.
1198
// Make the eigenvectors a right--handed system by changing sign on
1199
// the last column.
1200
rkRot[0][2] = -rkRot[0][2];
1201
rkRot[1][2] = -rkRot[1][2];
1202
rkRot[2][2] = -rkRot[2][2];
1203
}
1204
}
1205
1206
template <class Real>
1207
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesXYZ (Real fXAngle, Real fYAngle,
1208
Real fZAngle)
1209
{
1210
Real fCos, fSin;
1211
1212
fCos = moMath<Real>::Cos(fXAngle);
1213
fSin = moMath<Real>::Sin(fXAngle);
1214
moMatrix3 kXMat(
1215
(Real)1.0,(Real)0.0,(Real)0.0,
1216
(Real)0.0,fCos,-fSin,
1217
(Real)0.0,fSin,fCos);
1218
1219
fCos = moMath<Real>::Cos(fYAngle);
1220
fSin = moMath<Real>::Sin(fYAngle);
1221
moMatrix3 kYMat(
1222
fCos,(Real)0.0,fSin,
1223
(Real)0.0,(Real)1.0,(Real)0.0,
1224
-fSin,(Real)0.0,fCos);
1225
1226
fCos = moMath<Real>::Cos(fZAngle);
1227
fSin = moMath<Real>::Sin(fZAngle);
1228
moMatrix3 kZMat(
1229
fCos,-fSin,(Real)0.0,
1230
fSin,fCos,(Real)0.0,
1231
(Real)0.0,(Real)0.0,(Real)1.0);
1232
1233
*this = kXMat*(kYMat*kZMat);
1234
return *this;
1235
}
1236
1237
template <class Real>
1238
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesXZY (Real fXAngle, Real fZAngle,
1239
Real fYAngle)
1240
{
1241
Real fCos, fSin;
1242
1243
fCos = moMath<Real>::Cos(fXAngle);
1244
fSin = moMath<Real>::Sin(fXAngle);
1245
moMatrix3 kXMat(
1246
(Real)1.0,(Real)0.0,(Real)0.0,
1247
(Real)0.0,fCos,-fSin,
1248
(Real)0.0,fSin,fCos);
1249
1250
fCos = moMath<Real>::Cos(fZAngle);
1251
fSin = moMath<Real>::Sin(fZAngle);
1252
moMatrix3 kZMat(
1253
fCos,-fSin,(Real)0.0,
1254
fSin,fCos,(Real)0.0,
1255
(Real)0.0,(Real)0.0,(Real)1.0);
1256
1257
fCos = moMath<Real>::Cos(fYAngle);
1258
fSin = moMath<Real>::Sin(fYAngle);
1259
moMatrix3 kYMat(
1260
fCos,(Real)0.0,fSin,
1261
(Real)0.0,(Real)1.0,(Real)0.0,
1262
-fSin,(Real)0.0,fCos);
1263
1264
*this = kXMat*(kZMat*kYMat);
1265
return *this;
1266
}
1267
1268
template <class Real>
1269
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesYXZ (Real fYAngle, Real fXAngle,
1270
Real fZAngle)
1271
{
1272
Real fCos, fSin;
1273
1274
fCos = moMath<Real>::Cos(fYAngle);
1275
fSin = moMath<Real>::Sin(fYAngle);
1276
moMatrix3 kYMat(
1277
fCos,(Real)0.0,fSin,
1278
(Real)0.0,(Real)1.0,(Real)0.0,
1279
-fSin,(Real)0.0,fCos);
1280
1281
fCos = moMath<Real>::Cos(fXAngle);
1282
fSin = moMath<Real>::Sin(fXAngle);
1283
moMatrix3 kXMat(
1284
(Real)1.0,(Real)0.0,(Real)0.0,
1285
(Real)0.0,fCos,-fSin,
1286
(Real)0.0,fSin,fCos);
1287
1288
fCos = moMath<Real>::Cos(fZAngle);
1289
fSin = moMath<Real>::Sin(fZAngle);
1290
moMatrix3 kZMat(
1291
fCos,-fSin,(Real)0.0,
1292
fSin,fCos,(Real)0.0,
1293
(Real)0.0,(Real)0.0,(Real)1.0);
1294
1295
*this = kYMat*(kXMat*kZMat);
1296
return *this;
1297
}
1298
1299
template <class Real>
1300
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesYZX (Real fYAngle, Real fZAngle,
1301
Real fXAngle)
1302
{
1303
Real fCos, fSin;
1304
1305
fCos = moMath<Real>::Cos(fYAngle);
1306
fSin = moMath<Real>::Sin(fYAngle);
1307
moMatrix3 kYMat(
1308
fCos,(Real)0.0,fSin,
1309
(Real)0.0,(Real)1.0,(Real)0.0,
1310
-fSin,(Real)0.0,fCos);
1311
1312
fCos = moMath<Real>::Cos(fZAngle);
1313
fSin = moMath<Real>::Sin(fZAngle);
1314
moMatrix3 kZMat(
1315
fCos,-fSin,(Real)0.0,
1316
fSin,fCos,(Real)0.0,
1317
(Real)0.0,(Real)0.0,(Real)1.0);
1318
1319
fCos = moMath<Real>::Cos(fXAngle);
1320
fSin = moMath<Real>::Sin(fXAngle);
1321
moMatrix3 kXMat(
1322
(Real)1.0,(Real)0.0,(Real)0.0,
1323
(Real)0.0,fCos,-fSin,
1324
(Real)0.0,fSin,fCos);
1325
1326
*this = kYMat*(kZMat*kXMat);
1327
return *this;
1328
}
1329
1330
template <class Real>
1331
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesZXY (Real fZAngle, Real fXAngle,
1332
Real fYAngle)
1333
{
1334
Real fCos, fSin;
1335
1336
fCos = moMath<Real>::Cos(fZAngle);
1337
fSin = moMath<Real>::Sin(fZAngle);
1338
moMatrix3 kZMat(
1339
fCos,-fSin,(Real)0.0,
1340
fSin,fCos,(Real)0.0,
1341
(Real)0.0,(Real)0.0,(Real)1.0);
1342
1343
fCos = moMath<Real>::Cos(fXAngle);
1344
fSin = moMath<Real>::Sin(fXAngle);
1345
moMatrix3 kXMat(
1346
(Real)1.0,(Real)0.0,(Real)0.0,
1347
(Real)0.0,fCos,-fSin,
1348
(Real)0.0,fSin,fCos);
1349
1350
fCos = moMath<Real>::Cos(fYAngle);
1351
fSin = moMath<Real>::Sin(fYAngle);
1352
moMatrix3 kYMat(
1353
fCos,(Real)0.0,fSin,
1354
(Real)0.0,(Real)1.0,(Real)0.0,
1355
-fSin,(Real)0.0,fCos);
1356
1357
*this = kZMat*(kXMat*kYMat);
1358
return *this;
1359
}
1360
1361
template <class Real>
1362
moMatrix3<Real>& moMatrix3<Real>::FromEulerAnglesZYX (Real fZAngle, Real fYAngle,
1363
Real fXAngle)
1364
{
1365
Real fCos, fSin;
1366
1367
fCos = moMath<Real>::Cos(fZAngle);
1368
fSin = moMath<Real>::Sin(fZAngle);
1369
moMatrix3 kZMat(
1370
fCos,-fSin,(Real)0.0,
1371
fSin,fCos,(Real)0.0,
1372
(Real)0.0,(Real)0.0,(Real)1.0);
1373
1374
fCos = moMath<Real>::Cos(fYAngle);
1375
fSin = moMath<Real>::Sin(fYAngle);
1376
moMatrix3 kYMat(
1377
fCos,(Real)0.0,fSin,
1378
(Real)0.0,(Real)1.0,(Real)0.0,
1379
-fSin,(Real)0.0,fCos);
1380
1381
fCos = moMath<Real>::Cos(fXAngle);
1382
fSin = moMath<Real>::Sin(fXAngle);
1383
moMatrix3 kXMat(
1384
(Real)1.0,(Real)0.0,(Real)0.0,
1385
(Real)0.0,fCos,-fSin,
1386
(Real)0.0,fSin,fCos);
1387
1388
*this = kZMat*(kYMat*kXMat);
1389
return *this;
1390
}
1391
1392
template <class Real>
1393
bool moMatrix3<Real>::ToEulerAnglesXYZ (Real& rfXAngle, Real& rfYAngle,
1394
Real& rfZAngle) const
1395
{
1396
// rot = cy*cz -cy*sz sy
1397
// cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
1398
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
1399
1400
if (m_afEntry[2] < (Real)1.0)
1401
{
1402
if (m_afEntry[2] > -(Real)1.0)
1403
{
1404
rfXAngle = moMath<Real>::ATan2(-m_afEntry[5],m_afEntry[8]);
1405
rfYAngle = (Real)asin((double)m_afEntry[2]);
1406
rfZAngle = moMath<Real>::ATan2(-m_afEntry[1],m_afEntry[0]);
1407
return true;
1408
}
1409
else
1410
{
1411
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
1412
rfXAngle = -moMath<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
1413
rfYAngle = -moMath<Real>::HALF_PI;
1414
rfZAngle = (Real)0.0;
1415
return false;
1416
}
1417
}
1418
else
1419
{
1420
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
1421
rfXAngle = moMath<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
1422
rfYAngle = moMath<Real>::HALF_PI;
1423
rfZAngle = (Real)0.0;
1424
return false;
1425
}
1426
}
1427
1428
template <class Real>
1429
bool moMatrix3<Real>::ToEulerAnglesXZY (Real& rfXAngle, Real& rfZAngle,
1430
Real& rfYAngle) const
1431
{
1432
// rot = cy*cz -sz cz*sy
1433
// sx*sy+cx*cy*sz cx*cz -cy*sx+cx*sy*sz
1434
// -cx*sy+cy*sx*sz cz*sx cx*cy+sx*sy*sz
1435
1436
if (m_afEntry[1] < (Real)1.0)
1437
{
1438
if (m_afEntry[1] > -(Real)1.0)
1439
{
1440
rfXAngle = moMath<Real>::ATan2(m_afEntry[7],m_afEntry[4]);
1441
rfZAngle = (Real)asin(-(double)m_afEntry[1]);
1442
rfYAngle = moMath<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
1443
return true;
1444
}
1445
else
1446
{
1447
// WARNING. Not unique. XA - YA = atan2(r20,r22)
1448
rfXAngle = moMath<Real>::ATan2(m_afEntry[6],m_afEntry[8]);
1449
rfZAngle = moMath<Real>::HALF_PI;
1450
rfYAngle = (Real)0.0;
1451
return false;
1452
}
1453
}
1454
else
1455
{
1456
// WARNING. Not unique. XA + YA = atan2(-r20,r22)
1457
rfXAngle = moMath<Real>::ATan2(-m_afEntry[6],m_afEntry[8]);
1458
rfZAngle = -moMath<Real>::HALF_PI;
1459
rfYAngle = (Real)0.0;
1460
return false;
1461
}
1462
}
1463
1464
template <class Real>
1465
bool moMatrix3<Real>::ToEulerAnglesYXZ (Real& rfYAngle, Real& rfXAngle,
1466
Real& rfZAngle) const
1467
{
1468
// rot = cy*cz+sx*sy*sz cz*sx*sy-cy*sz cx*sy
1469
// cx*sz cx*cz -sx
1470
// -cz*sy+cy*sx*sz cy*cz*sx+sy*sz cx*cy
1471
1472
if (m_afEntry[5] < (Real)1.0)
1473
{
1474
if (m_afEntry[5] > -(Real)1.0)
1475
{
1476
rfYAngle = moMath<Real>::ATan2(m_afEntry[2],m_afEntry[8]);
1477
rfXAngle = (Real)asin(-(double)m_afEntry[5]);
1478
rfZAngle = moMath<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
1479
return true;
1480
}
1481
else
1482
{
1483
// WARNING. Not unique. YA - ZA = atan2(r01,r00)
1484
rfYAngle = moMath<Real>::ATan2(m_afEntry[1],m_afEntry[0]);
1485
rfXAngle = moMath<Real>::HALF_PI;
1486
rfZAngle = (Real)0.0;
1487
return false;
1488
}
1489
}
1490
else
1491
{
1492
// WARNING. Not unique. YA + ZA = atan2(-r01,r00)
1493
rfYAngle = moMath<Real>::ATan2(-m_afEntry[1],m_afEntry[0]);
1494
rfXAngle = -moMath<Real>::HALF_PI;
1495
rfZAngle = (Real)0.0;
1496
return false;
1497
}
1498
}
1499
1500
template <class Real>
1501
bool moMatrix3<Real>::ToEulerAnglesYZX (Real& rfYAngle, Real& rfZAngle,
1502
Real& rfXAngle) const
1503
{
1504
// rot = cy*cz sx*sy-cx*cy*sz cx*sy+cy*sx*sz
1505
// sz cx*cz -cz*sx
1506
// -cz*sy cy*sx+cx*sy*sz cx*cy-sx*sy*sz
1507
1508
if (m_afEntry[3] < (Real)1.0)
1509
{
1510
if (m_afEntry[3] > -(Real)1.0)
1511
{
1512
rfYAngle = moMath<Real>::ATan2(-m_afEntry[6],m_afEntry[0]);
1513
rfZAngle = (Real)asin((double)m_afEntry[3]);
1514
rfXAngle = moMath<Real>::ATan2(-m_afEntry[5],m_afEntry[4]);
1515
return true;
1516
}
1517
else
1518
{
1519
// WARNING. Not unique. YA - XA = -atan2(r21,r22);
1520
rfYAngle = -moMath<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
1521
rfZAngle = -moMath<Real>::HALF_PI;
1522
rfXAngle = (Real)0.0;
1523
return false;
1524
}
1525
}
1526
else
1527
{
1528
// WARNING. Not unique. YA + XA = atan2(r21,r22)
1529
rfYAngle = moMath<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
1530
rfZAngle = moMath<Real>::HALF_PI;
1531
rfXAngle = (Real)0.0;
1532
return false;
1533
}
1534
}
1535
1536
template <class Real>
1537
bool moMatrix3<Real>::ToEulerAnglesZXY (Real& rfZAngle, Real& rfXAngle,
1538
Real& rfYAngle) const
1539
{
1540
// rot = cy*cz-sx*sy*sz -cx*sz cz*sy+cy*sx*sz
1541
// cz*sx*sy+cy*sz cx*cz -cy*cz*sx+sy*sz
1542
// -cx*sy sx cx*cy
1543
1544
if (m_afEntry[7] < (Real)1.0)
1545
{
1546
if (m_afEntry[7] > -(Real)1.0)
1547
{
1548
rfZAngle = moMath<Real>::ATan2(-m_afEntry[1],m_afEntry[4]);
1549
rfXAngle = (Real)asin((double)m_afEntry[7]);
1550
rfYAngle = moMath<Real>::ATan2(-m_afEntry[6],m_afEntry[8]);
1551
return true;
1552
}
1553
else
1554
{
1555
// WARNING. Not unique. ZA - YA = -atan(r02,r00)
1556
rfZAngle = -moMath<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
1557
rfXAngle = -moMath<Real>::HALF_PI;
1558
rfYAngle = (Real)0.0;
1559
return false;
1560
}
1561
}
1562
else
1563
{
1564
// WARNING. Not unique. ZA + YA = atan2(r02,r00)
1565
rfZAngle = moMath<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
1566
rfXAngle = moMath<Real>::HALF_PI;
1567
rfYAngle = (Real)0.0;
1568
return false;
1569
}
1570
}
1571
1572
template <class Real>
1573
bool moMatrix3<Real>::ToEulerAnglesZYX (Real& rfZAngle, Real& rfYAngle,
1574
Real& rfXAngle) const
1575
{
1576
// rot = cy*cz cz*sx*sy-cx*sz cx*cz*sy+sx*sz
1577
// cy*sz cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
1578
// -sy cy*sx cx*cy
1579
1580
if (m_afEntry[6] < (Real)1.0)
1581
{
1582
if (m_afEntry[6] > -(Real)1.0)
1583
{
1584
rfZAngle = moMath<Real>::ATan2(m_afEntry[3],m_afEntry[0]);
1585
rfYAngle = (Real)asin(-(double)m_afEntry[6]);
1586
rfXAngle = moMath<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
1587
return true;
1588
}
1589
else
1590
{
1591
// WARNING. Not unique. ZA - XA = -atan2(r01,r02)
1592
rfZAngle = -moMath<Real>::ATan2(m_afEntry[1],m_afEntry[2]);
1593
rfYAngle = moMath<Real>::HALF_PI;
1594
rfXAngle = (Real)0.0;
1595
return false;
1596
}
1597
}
1598
else
1599
{
1600
// WARNING. Not unique. ZA + XA = atan2(-r01,-r02)
1601
rfZAngle = moMath<Real>::ATan2(-m_afEntry[1],-m_afEntry[2]);
1602
rfYAngle = -moMath<Real>::HALF_PI;
1603
rfXAngle = (Real)0.0;
1604
return false;
1605
}
1606
}
1607
1608
template <class Real>
1609
moMatrix3<Real>& moMatrix3<Real>::Slerp (Real fT, const moMatrix3& rkR0,
1610
const moMatrix3& rkR1)
1611
{
1612
moVector3<Real> kAxis;
1613
Real fAngle;
1614
moMatrix3 kProd = rkR0.TransposeTimes(rkR1);
1615
kProd.ToAxisAngle(kAxis,fAngle);
1616
FromAxisAngle(kAxis,fT*fAngle);
1617
return *this;
1618
}
1619
1620
template <class Real>
1621
bool moMatrix3<Real>::Tridiagonalize (Real afDiag[3], Real afSubd[2])
1622
{
1623
// Householder reduction T = Q^t M Q
1624
// Input:
1625
// mat, symmetric 3x3 matrix M
1626
// Output:
1627
// mat, orthogonal matrix Q (a reflection)
1628
// diag, diagonal entries of T
1629
// subd, subdiagonal entries of T (T is symmetric)
1630
1631
Real fM00 = m_afEntry[0];
1632
Real fM01 = m_afEntry[1];
1633
Real fM02 = m_afEntry[2];
1634
Real fM11 = m_afEntry[4];
1635
Real fM12 = m_afEntry[5];
1636
Real fM22 = m_afEntry[8];
1637
1638
afDiag[0] = fM00;
1639
if (moMath<Real>::FAbs(fM02) >= moMath<Real>::ZERO_TOLERANCE)
1640
{
1641
afSubd[0] = moMath<Real>::Sqrt(fM01*fM01+fM02*fM02);
1642
Real fInvLength = ((Real)1.0)/afSubd[0];
1643
fM01 *= fInvLength;
1644
fM02 *= fInvLength;
1645
Real fTmp = ((Real)2.0)*fM01*fM12+fM02*(fM22-fM11);
1646
afDiag[1] = fM11+fM02*fTmp;
1647
afDiag[2] = fM22-fM02*fTmp;
1648
afSubd[1] = fM12-fM01*fTmp;
1649
1650
m_afEntry[0] = (Real)1.0;
1651
m_afEntry[1] = (Real)0.0;
1652
m_afEntry[2] = (Real)0.0;
1653
m_afEntry[3] = (Real)0.0;
1654
m_afEntry[4] = fM01;
1655
m_afEntry[5] = fM02;
1656
m_afEntry[6] = (Real)0.0;
1657
m_afEntry[7] = fM02;
1658
m_afEntry[8] = -fM01;
1659
return true;
1660
}
1661
else
1662
{
1663
afDiag[1] = fM11;
1664
afDiag[2] = fM22;
1665
afSubd[0] = fM01;
1666
afSubd[1] = fM12;
1667
1668
m_afEntry[0] = (Real)1.0;
1669
m_afEntry[1] = (Real)0.0;
1670
m_afEntry[2] = (Real)0.0;
1671
m_afEntry[3] = (Real)0.0;
1672
m_afEntry[4] = (Real)1.0;
1673
m_afEntry[5] = (Real)0.0;
1674
m_afEntry[6] = (Real)0.0;
1675
m_afEntry[7] = (Real)0.0;
1676
m_afEntry[8] = (Real)1.0;
1677
return false;
1678
}
1679
}
1680
1681
template <class Real>
1682
bool moMatrix3<Real>::QLAlgorithm (Real afDiag[3], Real afSubd[2])
1683
{
1684
// This is an implementation of the symmetric QR algorithm from the book
1685
// "Matrix Computations" by Gene H. Golub and Charles F. Van Loan, second
1686
// edition. The algorithm is 8.2.3. The implementation has a slight
1687
// variation to actually make it a QL algorithm, and it traps the case
1688
// when either of the subdiagonal terms s0 or s1 is zero and reduces the
1689
// 2-by-2 subblock directly.
1690
1691
const int iMax = 32;
1692
for (int i = 0; i < iMax; i++)
1693
{
1694
Real fSum, fDiff, fDiscr, fEValue0, fEValue1, fCos, fSin, fTmp;
1695
int iRow;
1696
1697
fSum = moMath<Real>::FAbs(afDiag[0]) + moMath<Real>::FAbs(afDiag[1]);
1698
if (moMath<Real>::FAbs(afSubd[0]) + fSum == fSum)
1699
{
1700
// The matrix is effectively
1701
// +- -+
1702
// M = | d0 0 0 |
1703
// | 0 d1 s1 |
1704
// | 0 s1 d2 |
1705
// +- -+
1706
1707
// Compute the eigenvalues as roots of a quadratic equation.
1708
fSum = afDiag[1] + afDiag[2];
1709
fDiff = afDiag[1] - afDiag[2];
1710
fDiscr = moMath<Real>::Sqrt(fDiff*fDiff +
1711
((Real)4.0)*afSubd[1]*afSubd[1]);
1712
fEValue0 = ((Real)0.5)*(fSum - fDiscr);
1713
fEValue1 = ((Real)0.5)*(fSum + fDiscr);
1714
1715
// Compute the Givens rotation.
1716
if (fDiff >= (Real)0.0)
1717
{
1718
fCos = afSubd[1];
1719
fSin = afDiag[1] - fEValue0;
1720
}
1721
else
1722
{
1723
fCos = afDiag[2] - fEValue0;
1724
fSin = afSubd[1];
1725
}
1726
fTmp = moMath<Real>::InvSqrt(fCos*fCos + fSin*fSin);
1727
fCos *= fTmp;
1728
fSin *= fTmp;
1729
1730
// Postmultiply the current orthogonal matrix with the Givens
1731
// rotation.
1732
for (iRow = 0; iRow < 3; iRow++)
1733
{
1734
fTmp = m_afEntry[2+3*iRow];
1735
m_afEntry[2+3*iRow] = fSin*m_afEntry[1+3*iRow] + fCos*fTmp;
1736
m_afEntry[1+3*iRow] = fCos*m_afEntry[1+3*iRow] - fSin*fTmp;
1737
}
1738
1739
// Update the tridiagonal matrix.
1740
afDiag[1] = fEValue0;
1741
afDiag[2] = fEValue1;
1742
afSubd[0] = (Real)0.0;
1743
afSubd[1] = (Real)0.0;
1744
return true;
1745
}
1746
1747
fSum = moMath<Real>::FAbs(afDiag[1]) + moMath<Real>::FAbs(afDiag[2]);
1748
if (moMath<Real>::FAbs(afSubd[1]) + fSum == fSum)
1749
{
1750
// The matrix is effectively
1751
// +- -+
1752
// M = | d0 s0 0 |
1753
// | s0 d1 0 |
1754
// | 0 0 d2 |
1755
// +- -+
1756
1757
// Compute the eigenvalues as roots of a quadratic equation.
1758
fSum = afDiag[0] + afDiag[1];
1759
fDiff = afDiag[0] - afDiag[1];
1760
fDiscr = moMath<Real>::Sqrt(fDiff*fDiff +
1761
((Real)4.0)*afSubd[0]*afSubd[0]);
1762
fEValue0 = ((Real)0.5)*(fSum - fDiscr);
1763
fEValue1 = ((Real)0.5)*(fSum + fDiscr);
1764
1765
// Compute the Givens rotation.
1766
if (fDiff >= (Real)0.0)
1767
{
1768
fCos = afSubd[0];
1769
fSin = afDiag[0] - fEValue0;
1770
}
1771
else
1772
{
1773
fCos = afDiag[1] - fEValue0;
1774
fSin = afSubd[0];
1775
}
1776
fTmp = moMath<Real>::InvSqrt(fCos*fCos + fSin*fSin);
1777
fCos *= fTmp;
1778
fSin *= fTmp;
1779
1780
// Postmultiply the current orthogonal matrix with the Givens
1781
// rotation.
1782
for (iRow = 0; iRow < 3; iRow++)
1783
{
1784
fTmp = m_afEntry[1+3*iRow];
1785
m_afEntry[1+3*iRow] = fSin*m_afEntry[0+3*iRow] + fCos*fTmp;
1786
m_afEntry[0+3*iRow] = fCos*m_afEntry[0+3*iRow] - fSin*fTmp;
1787
}
1788
1789
// Update the tridiagonal matrix.
1790
afDiag[0] = fEValue0;
1791
afDiag[1] = fEValue1;
1792
afSubd[0] = (Real)0.0;
1793
afSubd[1] = (Real)0.0;
1794
return true;
1795
}
1796
1797
// The matrix is
1798
// +- -+
1799
// M = | d0 s0 0 |
1800
// | s0 d1 s1 |
1801
// | 0 s1 d2 |
1802
// +- -+
1803
1804
// Set up the parameters for the first pass of the QL step. The
1805
// value for A is the difference between diagonal term D[2] and the
1806
// implicit shift suggested by Wilkinson.
1807
Real fRatio = (afDiag[1]-afDiag[0])/(((Real)2.0f)*afSubd[0]);
1808
Real fRoot = moMath<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
1809
Real fB = afSubd[1];
1810
Real fA = afDiag[2] - afDiag[0];
1811
if (fRatio >= (Real)0.0)
1812
{
1813
fA += afSubd[0]/(fRatio + fRoot);
1814
}
1815
else
1816
{
1817
fA += afSubd[0]/(fRatio - fRoot);
1818
}
1819
1820
// Compute the Givens rotation for the first pass.
1821
if (moMath<Real>::FAbs(fB) >= moMath<Real>::FAbs(fA))
1822
{
1823
fRatio = fA/fB;
1824
fSin = moMath<Real>::InvSqrt((Real)1.0 + fRatio*fRatio);
1825
fCos = fRatio*fSin;
1826
}
1827
else
1828
{
1829
fRatio = fB/fA;
1830
fCos = moMath<Real>::InvSqrt((Real)1.0 + fRatio*fRatio);
1831
fSin = fRatio*fCos;
1832
}
1833
1834
// Postmultiply the current orthogonal matrix with the Givens
1835
// rotation.
1836
for (iRow = 0; iRow < 3; iRow++)
1837
{
1838
fTmp = m_afEntry[2+3*iRow];
1839
m_afEntry[2+3*iRow] = fSin*m_afEntry[1+3*iRow]+fCos*fTmp;
1840
m_afEntry[1+3*iRow] = fCos*m_afEntry[1+3*iRow]-fSin*fTmp;
1841
}
1842
1843
// Set up the parameters for the second pass of the QL step. The
1844
// values tmp0 and tmp1 are required to fully update the tridiagonal
1845
// matrix at the end of the second pass.
1846
Real fTmp0 = (afDiag[1] - afDiag[2])*fSin +
1847
((Real)2.0)*afSubd[1]*fCos;
1848
Real fTmp1 = fCos*afSubd[0];
1849
fB = fSin*afSubd[0];
1850
fA = fCos*fTmp0 - afSubd[1];
1851
fTmp0 *= fSin;
1852
1853
// Compute the Givens rotation for the second pass. The subdiagonal
1854
// term S[1] in the tridiagonal matrix is updated at this time.
1855
if (moMath<Real>::FAbs(fB) >= moMath<Real>::FAbs(fA))
1856
{
1857
fRatio = fA/fB;
1858
fRoot = moMath<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
1859
afSubd[1] = fB*fRoot;
1860
fSin = ((Real)1.0)/fRoot;
1861
fCos = fRatio*fSin;
1862
}
1863
else
1864
{
1865
fRatio = fB/fA;
1866
fRoot = moMath<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
1867
afSubd[1] = fA*fRoot;
1868
fCos = ((Real)1.0)/fRoot;
1869
fSin = fRatio*fCos;
1870
}
1871
1872
// Postmultiply the current orthogonal matrix with the Givens
1873
// rotation.
1874
for (iRow = 0; iRow < 3; iRow++)
1875
{
1876
fTmp = m_afEntry[1+3*iRow];
1877
m_afEntry[1+3*iRow] = fSin*m_afEntry[0+3*iRow]+fCos*fTmp;
1878
m_afEntry[0+3*iRow] = fCos*m_afEntry[0+3*iRow]-fSin*fTmp;
1879
}
1880
1881
// Complete the update of the tridiagonal matrix.
1882
Real fTmp2 = afDiag[1] - fTmp0;
1883
afDiag[2] += fTmp0;
1884
fTmp0 = (afDiag[0] - fTmp2)*fSin + ((Real)2.0)*fTmp1*fCos;
1885
afSubd[0] = fCos*fTmp0 - fTmp1;
1886
fTmp0 *= fSin;
1887
afDiag[1] = fTmp2 + fTmp0;
1888
afDiag[0] -= fTmp0;
1889
}
1890
return false;
1891
}
1892
1893
template <class Real>
1894
void moMatrix3<Real>::Bidiagonalize (moMatrix3& rkA, moMatrix3& rkL, moMatrix3& rkR)
1895
{
1896
Real afV[3], afW[3];
1897
Real fLength, fSign, fT1, fInvT1, fT2;
1898
bool bIdentity;
1899
1900
// map first column to (*,0,0)
1901
fLength = moMath<Real>::Sqrt(rkA[0][0]*rkA[0][0] + rkA[1][0]*rkA[1][0] +
1902
rkA[2][0]*rkA[2][0]);
1903
if (fLength > (Real)0.0)
1904
{
1905
fSign = (rkA[0][0] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
1906
fT1 = rkA[0][0] + fSign*fLength;
1907
fInvT1 = ((Real)1.0)/fT1;
1908
afV[1] = rkA[1][0]*fInvT1;
1909
afV[2] = rkA[2][0]*fInvT1;
1910
1911
fT2 = -((Real)2.0)/(((Real)1.0)+afV[1]*afV[1]+afV[2]*afV[2]);
1912
afW[0] = fT2*(rkA[0][0]+rkA[1][0]*afV[1]+rkA[2][0]*afV[2]);
1913
afW[1] = fT2*(rkA[0][1]+rkA[1][1]*afV[1]+rkA[2][1]*afV[2]);
1914
afW[2] = fT2*(rkA[0][2]+rkA[1][2]*afV[1]+rkA[2][2]*afV[2]);
1915
rkA[0][0] += afW[0];
1916
rkA[0][1] += afW[1];
1917
rkA[0][2] += afW[2];
1918
rkA[1][1] += afV[1]*afW[1];
1919
rkA[1][2] += afV[1]*afW[2];
1920
rkA[2][1] += afV[2]*afW[1];
1921
rkA[2][2] += afV[2]*afW[2];
1922
1923
rkL[0][0] = ((Real)1.0)+fT2;
1924
rkL[0][1] = fT2*afV[1];
1925
rkL[1][0] = rkL[0][1];
1926
rkL[0][2] = fT2*afV[2];
1927
rkL[2][0] = rkL[0][2];
1928
rkL[1][1] = ((Real)1.0)+fT2*afV[1]*afV[1];
1929
rkL[1][2] = fT2*afV[1]*afV[2];
1930
rkL[2][1] = rkL[1][2];
1931
rkL[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
1932
bIdentity = false;
1933
}
1934
else
1935
{
1936
rkL = moMatrix3::IDENTITY;
1937
bIdentity = true;
1938
}
1939
1940
// map first row to (*,*,0)
1941
fLength = moMath<Real>::Sqrt(rkA[0][1]*rkA[0][1]+rkA[0][2]*rkA[0][2]);
1942
if (fLength > (Real)0.0)
1943
{
1944
fSign = (rkA[0][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
1945
fT1 = rkA[0][1] + fSign*fLength;
1946
afV[2] = rkA[0][2]/fT1;
1947
1948
fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
1949
afW[0] = fT2*(rkA[0][1]+rkA[0][2]*afV[2]);
1950
afW[1] = fT2*(rkA[1][1]+rkA[1][2]*afV[2]);
1951
afW[2] = fT2*(rkA[2][1]+rkA[2][2]*afV[2]);
1952
rkA[0][1] += afW[0];
1953
rkA[1][1] += afW[1];
1954
rkA[1][2] += afW[1]*afV[2];
1955
rkA[2][1] += afW[2];
1956
rkA[2][2] += afW[2]*afV[2];
1957
1958
rkR[0][0] = (Real)1.0;
1959
rkR[0][1] = (Real)0.0;
1960
rkR[1][0] = (Real)0.0;
1961
rkR[0][2] = (Real)0.0;
1962
rkR[2][0] = (Real)0.0;
1963
rkR[1][1] = ((Real)1.0)+fT2;
1964
rkR[1][2] = fT2*afV[2];
1965
rkR[2][1] = rkR[1][2];
1966
rkR[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
1967
}
1968
else
1969
{
1970
rkR = moMatrix3::IDENTITY;
1971
}
1972
1973
// map second column to (*,*,0)
1974
fLength = moMath<Real>::Sqrt(rkA[1][1]*rkA[1][1]+rkA[2][1]*rkA[2][1]);
1975
if (fLength > (Real)0.0)
1976
{
1977
fSign = (rkA[1][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
1978
fT1 = rkA[1][1] + fSign*fLength;
1979
afV[2] = rkA[2][1]/fT1;
1980
1981
fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
1982
afW[1] = fT2*(rkA[1][1]+rkA[2][1]*afV[2]);
1983
afW[2] = fT2*(rkA[1][2]+rkA[2][2]*afV[2]);
1984
rkA[1][1] += afW[1];
1985
rkA[1][2] += afW[2];
1986
rkA[2][2] += afV[2]*afW[2];
1987
1988
Real fA = ((Real)1.0)+fT2;
1989
Real fB = fT2*afV[2];
1990
Real fC = ((Real)1.0)+fB*afV[2];
1991
1992
if (bIdentity)
1993
{
1994
rkL[0][0] = (Real)1.0;
1995
rkL[0][1] = (Real)0.0;
1996
rkL[1][0] = (Real)0.0;
1997
rkL[0][2] = (Real)0.0;
1998
rkL[2][0] = (Real)0.0;
1999
rkL[1][1] = fA;
2000
rkL[1][2] = fB;
2001
rkL[2][1] = fB;
2002
rkL[2][2] = fC;
2003
}
2004
else
2005
{
2006
for (int iRow = 0; iRow < 3; iRow++)
2007
{
2008
Real fTmp0 = rkL[iRow][1];
2009
Real fTmp1 = rkL[iRow][2];
2010
rkL[iRow][1] = fA*fTmp0+fB*fTmp1;
2011
rkL[iRow][2] = fB*fTmp0+fC*fTmp1;
2012
}
2013
}
2014
}
2015
}
2016
2017
template <class Real>
2018
void moMatrix3<Real>::GolubKahanStep (moMatrix3& rkA, moMatrix3& rkL, moMatrix3& rkR)
2019
{
2020
Real fT11 = rkA[0][1]*rkA[0][1]+rkA[1][1]*rkA[1][1];
2021
Real fT22 = rkA[1][2]*rkA[1][2]+rkA[2][2]*rkA[2][2];
2022
Real fT12 = rkA[1][1]*rkA[1][2];
2023
Real fTrace = fT11+fT22;
2024
Real fDiff = fT11-fT22;
2025
Real fDiscr = moMath<Real>::Sqrt(fDiff*fDiff+((Real)4.0)*fT12*fT12);
2026
Real fRoot1 = ((Real)0.5)*(fTrace+fDiscr);
2027
Real fRoot2 = ((Real)0.5)*(fTrace-fDiscr);
2028
2029
// adjust right
2030
Real fY = rkA[0][0] - (moMath<Real>::FAbs(fRoot1-fT22) <=
2031
moMath<Real>::FAbs(fRoot2-fT22) ? fRoot1 : fRoot2);
2032
Real fZ = rkA[0][1];
2033
Real fInvLength = moMath<Real>::InvSqrt(fY*fY+fZ*fZ);
2034
Real fSin = fZ*fInvLength;
2035
Real fCos = -fY*fInvLength;
2036
2037
Real fTmp0 = rkA[0][0];
2038
Real fTmp1 = rkA[0][1];
2039
rkA[0][0] = fCos*fTmp0-fSin*fTmp1;
2040
rkA[0][1] = fSin*fTmp0+fCos*fTmp1;
2041
rkA[1][0] = -fSin*rkA[1][1];
2042
rkA[1][1] *= fCos;
2043
2044
int iRow;
2045
for (iRow = 0; iRow < 3; iRow++)
2046
{
2047
fTmp0 = rkR[0][iRow];
2048
fTmp1 = rkR[1][iRow];
2049
rkR[0][iRow] = fCos*fTmp0-fSin*fTmp1;
2050
rkR[1][iRow] = fSin*fTmp0+fCos*fTmp1;
2051
}
2052
2053
// adjust left
2054
fY = rkA[0][0];
2055
fZ = rkA[1][0];
2056
fInvLength = moMath<Real>::InvSqrt(fY*fY+fZ*fZ);
2057
fSin = fZ*fInvLength;
2058
fCos = -fY*fInvLength;
2059
2060
rkA[0][0] = fCos*rkA[0][0]-fSin*rkA[1][0];
2061
fTmp0 = rkA[0][1];
2062
fTmp1 = rkA[1][1];
2063
rkA[0][1] = fCos*fTmp0-fSin*fTmp1;
2064
rkA[1][1] = fSin*fTmp0+fCos*fTmp1;
2065
rkA[0][2] = -fSin*rkA[1][2];
2066
rkA[1][2] *= fCos;
2067
2068
int iCol;
2069
for (iCol = 0; iCol < 3; iCol++)
2070
{
2071
fTmp0 = rkL[iCol][0];
2072
fTmp1 = rkL[iCol][1];
2073
rkL[iCol][0] = fCos*fTmp0-fSin*fTmp1;
2074
rkL[iCol][1] = fSin*fTmp0+fCos*fTmp1;
2075
}
2076
2077
// adjust right
2078
fY = rkA[0][1];
2079
fZ = rkA[0][2];
2080
fInvLength = moMath<Real>::InvSqrt(fY*fY+fZ*fZ);
2081
fSin = fZ*fInvLength;
2082
fCos = -fY*fInvLength;
2083
2084
rkA[0][1] = fCos*rkA[0][1]-fSin*rkA[0][2];
2085
fTmp0 = rkA[1][1];
2086
fTmp1 = rkA[1][2];
2087
rkA[1][1] = fCos*fTmp0-fSin*fTmp1;
2088
rkA[1][2] = fSin*fTmp0+fCos*fTmp1;
2089
rkA[2][1] = -fSin*rkA[2][2];
2090
rkA[2][2] *= fCos;
2091
2092
for (iRow = 0; iRow < 3; iRow++)
2093
{
2094
fTmp0 = rkR[1][iRow];
2095
fTmp1 = rkR[2][iRow];
2096
rkR[1][iRow] = fCos*fTmp0-fSin*fTmp1;
2097
rkR[2][iRow] = fSin*fTmp0+fCos*fTmp1;
2098
}
2099
2100
// adjust left
2101
fY = rkA[1][1];
2102
fZ = rkA[2][1];
2103
fInvLength = moMath<Real>::InvSqrt(fY*fY+fZ*fZ);
2104
fSin = fZ*fInvLength;
2105
fCos = -fY*fInvLength;
2106
2107
rkA[1][1] = fCos*rkA[1][1]-fSin*rkA[2][1];
2108
fTmp0 = rkA[1][2];
2109
fTmp1 = rkA[2][2];
2110
rkA[1][2] = fCos*fTmp0-fSin*fTmp1;
2111
rkA[2][2] = fSin*fTmp0+fCos*fTmp1;
2112
2113
for (iCol = 0; iCol < 3; iCol++)
2114
{
2115
fTmp0 = rkL[iCol][1];
2116
fTmp1 = rkL[iCol][2];
2117
rkL[iCol][1] = fCos*fTmp0-fSin*fTmp1;
2118
rkL[iCol][2] = fSin*fTmp0+fCos*fTmp1;
2119
}
2120
}
2121
2122
template <class Real>
2123
void moMatrix3<Real>::SingularValueDecomposition (moMatrix3& rkL, moMatrix3& rkD,
2124
moMatrix3& rkRTranspose) const
2125
{
2126
int iRow, iCol;
2127
2128
moMatrix3 kA = *this;
2129
Bidiagonalize(kA,rkL,rkRTranspose);
2130
rkD.MakeZero();
2131
2132
const int iMax = 32;
2133
const Real fEpsilon = (Real)1e-04;
2134
for (int i = 0; i < iMax; i++)
2135
{
2136
Real fTmp, fTmp0, fTmp1;
2137
Real fSin0, fCos0, fTan0;
2138
Real fSin1, fCos1, fTan1;
2139
2140
bool bTest1 = (moMath<Real>::FAbs(kA[0][1]) <=
2141
fEpsilon*(moMath<Real>::FAbs(kA[0][0]) +
2142
moMath<Real>::FAbs(kA[1][1])));
2143
bool bTest2 = (moMath<Real>::FAbs(kA[1][2]) <=
2144
fEpsilon*(moMath<Real>::FAbs(kA[1][1]) +
2145
moMath<Real>::FAbs(kA[2][2])));
2146
if (bTest1)
2147
{
2148
if (bTest2)
2149
{
2150
rkD[0][0] = kA[0][0];
2151
rkD[1][1] = kA[1][1];
2152
rkD[2][2] = kA[2][2];
2153
break;
2154
}
2155
else
2156
{
2157
// 2x2 closed form factorization
2158
fTmp = (kA[1][1]*kA[1][1] - kA[2][2]*kA[2][2] +
2159
kA[1][2]*kA[1][2])/(kA[1][2]*kA[2][2]);
2160
fTan0 = ((Real)0.5)*(fTmp + moMath<Real>::Sqrt(fTmp*fTmp +
2161
((Real)4.0)));
2162
fCos0 = moMath<Real>::InvSqrt(((Real)1.0)+fTan0*fTan0);
2163
fSin0 = fTan0*fCos0;
2164
2165
for (iCol = 0; iCol < 3; iCol++)
2166
{
2167
fTmp0 = rkL[iCol][1];
2168
fTmp1 = rkL[iCol][2];
2169
rkL[iCol][1] = fCos0*fTmp0-fSin0*fTmp1;
2170
rkL[iCol][2] = fSin0*fTmp0+fCos0*fTmp1;
2171
}
2172
2173
fTan1 = (kA[1][2]-kA[2][2]*fTan0)/kA[1][1];
2174
fCos1 = moMath<Real>::InvSqrt(((Real)1.0)+fTan1*fTan1);
2175
fSin1 = -fTan1*fCos1;
2176
2177
for (iRow = 0; iRow < 3; iRow++)
2178
{
2179
fTmp0 = rkRTranspose[1][iRow];
2180
fTmp1 = rkRTranspose[2][iRow];
2181
rkRTranspose[1][iRow] = fCos1*fTmp0-fSin1*fTmp1;
2182
rkRTranspose[2][iRow] = fSin1*fTmp0+fCos1*fTmp1;
2183
}
2184
2185
rkD[0][0] = kA[0][0];
2186
rkD[1][1] = fCos0*fCos1*kA[1][1] -
2187
fSin1*(fCos0*kA[1][2]-fSin0*kA[2][2]);
2188
rkD[2][2] = fSin0*fSin1*kA[1][1] +
2189
fCos1*(fSin0*kA[1][2]+fCos0*kA[2][2]);
2190
break;
2191
}
2192
}
2193
else
2194
{
2195
if (bTest2)
2196
{
2197
// 2x2 closed form factorization
2198
fTmp = (kA[0][0]*kA[0][0] + kA[1][1]*kA[1][1] -
2199
kA[0][1]*kA[0][1])/(kA[0][1]*kA[1][1]);
2200
fTan0 = ((Real)0.5)*(-fTmp + moMath<Real>::Sqrt(fTmp*fTmp +
2201
((Real)4.0)));
2202
fCos0 = moMath<Real>::InvSqrt(((Real)1.0)+fTan0*fTan0);
2203
fSin0 = fTan0*fCos0;
2204
2205
for (iCol = 0; iCol < 3; iCol++)
2206
{
2207
fTmp0 = rkL[iCol][0];
2208
fTmp1 = rkL[iCol][1];
2209
rkL[iCol][0] = fCos0*fTmp0-fSin0*fTmp1;
2210
rkL[iCol][1] = fSin0*fTmp0+fCos0*fTmp1;
2211
}
2212
2213
fTan1 = (kA[0][1]-kA[1][1]*fTan0)/kA[0][0];
2214
fCos1 = moMath<Real>::InvSqrt(((Real)1.0)+fTan1*fTan1);
2215
fSin1 = -fTan1*fCos1;
2216
2217
for (iRow = 0; iRow < 3; iRow++)
2218
{
2219
fTmp0 = rkRTranspose[0][iRow];
2220
fTmp1 = rkRTranspose[1][iRow];
2221
rkRTranspose[0][iRow] = fCos1*fTmp0-fSin1*fTmp1;
2222
rkRTranspose[1][iRow] = fSin1*fTmp0+fCos1*fTmp1;
2223
}
2224
2225
rkD[0][0] = fCos0*fCos1*kA[0][0] -
2226
fSin1*(fCos0*kA[0][1]-fSin0*kA[1][1]);
2227
rkD[1][1] = fSin0*fSin1*kA[0][0] +
2228
fCos1*(fSin0*kA[0][1]+fCos0*kA[1][1]);
2229
rkD[2][2] = kA[2][2];
2230
break;
2231
}
2232
else
2233
{
2234
GolubKahanStep(kA,rkL,rkRTranspose);
2235
}
2236
}
2237
}
2238
2239
// Make the diagonal entries positive.
2240
for (iRow = 0; iRow < 3; iRow++)
2241
{
2242
if (rkD[iRow][iRow] < (Real)0.0)
2243
{
2244
rkD[iRow][iRow] = -rkD[iRow][iRow];
2245
for (iCol = 0; iCol < 3; iCol++)
2246
{
2247
rkRTranspose[iRow][iCol] = -rkRTranspose[iRow][iCol];
2248
}
2249
}
2250
}
2251
}
2252
2253
template <class Real>
2254
void moMatrix3<Real>::SingularValueComposition (const moMatrix3& rkL,
2255
const moMatrix3& rkD, const moMatrix3& rkRTranspose)
2256
{
2257
*this = rkL*(rkD*rkRTranspose);
2258
}
2259
2260
template <class Real>
2261
void moMatrix3<Real>::PolarDecomposition (moMatrix3& rkQ, moMatrix3& rkS)
2262
{
2263
// Decompose M = L*D*R^T.
2264
moMatrix3 kL, kD, kRTranspose;
2265
SingularValueDecomposition(kL,kD,kRTranspose);
2266
2267
// Compute Q = L*R^T.
2268
rkQ = kL*kRTranspose;
2269
2270
// Compute S = R*D*R^T.
2271
rkS = kRTranspose.TransposeTimes(kD*kRTranspose);
2272
2273
// Numerical round-off errors can cause S not to be symmetric in the
2274
// sense that S[i][j] and S[j][i] are slightly different for i != j.
2275
// Correct this by averaging S and Transpose(S).
2276
rkS[0][1] = ((Real)0.5)*(rkS[0][1] + rkS[1][0]);
2277
rkS[1][0] = rkS[0][1];
2278
rkS[0][2] = ((Real)0.5)*(rkS[0][2] + rkS[2][0]);
2279
rkS[2][0] = rkS[0][2];
2280
rkS[1][2] = ((Real)0.5)*(rkS[1][2] + rkS[2][1]);
2281
rkS[2][1] = rkS[1][2];
2282
}
2283
2284
template <class Real>
2285
void moMatrix3<Real>::QDUDecomposition (moMatrix3& rkQ, moMatrix3& rkD,
2286
moMatrix3& rkU) const
2287
{
2288
// Factor M = QR = QDU where Q is orthogonal (rotation), D is diagonal
2289
// (scaling), and U is upper triangular with ones on its diagonal
2290
// (shear). Algorithm uses Gram-Schmidt orthogonalization (the QR
2291
// algorithm).
2292
//
2293
// If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then
2294
//
2295
// q0 = m0/|m0|
2296
// q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
2297
// q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
2298
//
2299
// where |V| indicates length of vector V and A*B indicates dot
2300
// product of vectors A and B. The matrix R has entries
2301
//
2302
// r00 = q0*m0 r01 = q0*m1 r02 = q0*m2
2303
// r10 = 0 r11 = q1*m1 r12 = q1*m2
2304
// r20 = 0 r21 = 0 r22 = q2*m2
2305
//
2306
// so D = diag(r00,r11,r22) and U has entries u01 = r01/r00,
2307
// u02 = r02/r00, and u12 = r12/r11.
2308
2309
// build orthogonal matrix Q
2310
Real fInvLength = moMath<Real>::InvSqrt(m_afEntry[0]*m_afEntry[0] +
2311
m_afEntry[3]*m_afEntry[3] + m_afEntry[6]*m_afEntry[6]);
2312
rkQ[0][0] = m_afEntry[0]*fInvLength;
2313
rkQ[1][0] = m_afEntry[3]*fInvLength;
2314
rkQ[2][0] = m_afEntry[6]*fInvLength;
2315
2316
Real fDot = rkQ[0][0]*m_afEntry[1] + rkQ[1][0]*m_afEntry[4] +
2317
rkQ[2][0]*m_afEntry[7];
2318
rkQ[0][1] = m_afEntry[1]-fDot*rkQ[0][0];
2319
rkQ[1][1] = m_afEntry[4]-fDot*rkQ[1][0];
2320
rkQ[2][1] = m_afEntry[7]-fDot*rkQ[2][0];
2321
fInvLength = moMath<Real>::InvSqrt(rkQ[0][1]*rkQ[0][1] +
2322
rkQ[1][1]*rkQ[1][1] + rkQ[2][1]*rkQ[2][1]);
2323
rkQ[0][1] *= fInvLength;
2324
rkQ[1][1] *= fInvLength;
2325
rkQ[2][1] *= fInvLength;
2326
2327
fDot = rkQ[0][0]*m_afEntry[2] + rkQ[1][0]*m_afEntry[5] +
2328
rkQ[2][0]*m_afEntry[8];
2329
rkQ[0][2] = m_afEntry[2]-fDot*rkQ[0][0];
2330
rkQ[1][2] = m_afEntry[5]-fDot*rkQ[1][0];
2331
rkQ[2][2] = m_afEntry[8]-fDot*rkQ[2][0];
2332
fDot = rkQ[0][1]*m_afEntry[2] + rkQ[1][1]*m_afEntry[5] +
2333
rkQ[2][1]*m_afEntry[8];
2334
rkQ[0][2] -= fDot*rkQ[0][1];
2335
rkQ[1][2] -= fDot*rkQ[1][1];
2336
rkQ[2][2] -= fDot*rkQ[2][1];
2337
fInvLength = moMath<Real>::InvSqrt(rkQ[0][2]*rkQ[0][2] +
2338
rkQ[1][2]*rkQ[1][2] + rkQ[2][2]*rkQ[2][2]);
2339
rkQ[0][2] *= fInvLength;
2340
rkQ[1][2] *= fInvLength;
2341
rkQ[2][2] *= fInvLength;
2342
2343
// guarantee that orthogonal matrix has determinant 1 (no reflections)
2344
Real fDet = rkQ[0][0]*rkQ[1][1]*rkQ[2][2] + rkQ[0][1]*rkQ[1][2]*rkQ[2][0]
2345
+ rkQ[0][2]*rkQ[1][0]*rkQ[2][1] - rkQ[0][2]*rkQ[1][1]*rkQ[2][0]
2346
- rkQ[0][1]*rkQ[1][0]*rkQ[2][2] - rkQ[0][0]*rkQ[1][2]*rkQ[2][1];
2347
2348
if (fDet < (Real)0.0)
2349
{
2350
for (int iRow = 0; iRow < 3; iRow++)
2351
{
2352
for (int iCol = 0; iCol < 3; iCol++)
2353
{
2354
rkQ[iRow][iCol] = -rkQ[iRow][iCol];
2355
}
2356
}
2357
}
2358
2359
// build "right" matrix R
2360
moMatrix3 kR;
2361
kR[0][0] = rkQ[0][0]*m_afEntry[0] + rkQ[1][0]*m_afEntry[3] +
2362
rkQ[2][0]*m_afEntry[6];
2363
kR[0][1] = rkQ[0][0]*m_afEntry[1] + rkQ[1][0]*m_afEntry[4] +
2364
rkQ[2][0]*m_afEntry[7];
2365
kR[1][1] = rkQ[0][1]*m_afEntry[1] + rkQ[1][1]*m_afEntry[4] +
2366
rkQ[2][1]*m_afEntry[7];
2367
kR[0][2] = rkQ[0][0]*m_afEntry[2] + rkQ[1][0]*m_afEntry[5] +
2368
rkQ[2][0]*m_afEntry[8];
2369
kR[1][2] = rkQ[0][1]*m_afEntry[2] + rkQ[1][1]*m_afEntry[5] +
2370
rkQ[2][1]*m_afEntry[8];
2371
kR[2][2] = rkQ[0][2]*m_afEntry[2] + rkQ[1][2]*m_afEntry[5] +
2372
rkQ[2][2]*m_afEntry[8];
2373
2374
// the scaling component
2375
rkD.MakeDiagonal(kR[0][0],kR[1][1],kR[2][2]);
2376
2377
// the shear component
2378
Real fInvD0 = ((Real)1.0)/rkD[0][0];
2379
rkU[0][0] = (Real)1.0;
2380
rkU[0][1] = kR[0][1]*fInvD0;
2381
rkU[0][2] = kR[0][2]*fInvD0;
2382
rkU[1][0] = (Real)0.0;
2383
rkU[1][1] = (Real)1.0;
2384
rkU[1][2] = kR[1][2]/rkD[1][1];
2385
rkU[2][0] = (Real)0.0;
2386
rkU[2][1] = (Real)0.0;
2387
rkU[2][2] = (Real)1.0;
2388
}
2389
*/
2390
2391
template<>
const
moMatrix3
<
MOfloat
>
moMatrix3
<
MOfloat
>::ZERO(
2392
0.0f,0.0f,0.0f,
2393
0.0f,0.0f,0.0f,
2394
0.0f,0.0f,0.0f);
2395
template<>
const
moMatrix3
<
MOfloat
>
moMatrix3
<
MOfloat
>::IDENTITY(
2396
1.0f,0.0f,0.0f,
2397
0.0f,1.0f,0.0f,
2398
0.0f,0.0f,1.0f);
2399
2400
template<>
const
moMatrix3
<
MOdouble
>
moMatrix3
<
MOdouble
>::ZERO(
2401
0.0,0.0,0.0,
2402
0.0,0.0,0.0,
2403
0.0,0.0,0.0);
2404
template<>
const
moMatrix3
<
MOdouble
>
moMatrix3
<
MOdouble
>::IDENTITY(
2405
1.0,0.0,0.0,
2406
0.0,1.0,0.0,
2407
0.0,0.0,1.0);
2408
2409
// momoMatrix4 class ------------------------------------------------------------
2410
2411
2412
template<>
const
moMatrix4<
MOfloat
> moMatrix4<
MOfloat
>::ZERO(
2413
0.0f,0.0f,0.0f,0.0f,
2414
0.0f,0.0f,0.0f,0.0f,
2415
0.0f,0.0f,0.0f,0.0f,
2416
0.0f,0.0f,0.0f,0.0f);
2417
template<>
const
moMatrix4<
MOfloat
> moMatrix4<
MOfloat
>::IDENTITY(
2418
1.0f,0.0f,0.0f,0.0f,
2419
0.0f,1.0f,0.0f,0.0f,
2420
0.0f,0.0f,1.0f,0.0f,
2421
0.0f,0.0f,0.0f,1.0f);
2422
2423
template<>
const
moMatrix4<
MOdouble
> moMatrix4<
MOdouble
>::ZERO(
2424
0.0,0.0,0.0,0.0,
2425
0.0,0.0,0.0,0.0,
2426
0.0,0.0,0.0,0.0,
2427
0.0,0.0,0.0,0.0);
2428
template<>
const
moMatrix4<
MOdouble
> moMatrix4<
MOdouble
>::IDENTITY(
2429
1.0,0.0,0.0,0.0,
2430
0.0,1.0,0.0,0.0,
2431
0.0,0.0,1.0,0.0,
2432
0.0,0.0,0.0,1.0);
2433
moArray.h
f
f
Definition:
jquery.js:71
MOfloat
#define MOfloat
Definition:
moTypes.h:403
moMathMatrix.h
moMatrix2
Definition:
moMathMatrix.h:87
moDefineDynamicArray
#define moDefineDynamicArray(name)
Definition:
moArray.cpp:222
MOdouble
#define MOdouble
Definition:
moTypes.h:404
moMatrix3
moMatrix3(const moMatrix3 &rkM)
Definition:
moMathMatrix.h:669
const
moPort const
Definition:
all_14.js:19
libmoldeo
moMathMatrix.cpp
Generado el Jueves, 18 de Enero de 2018 13:10:28 para libmoldeo (Moldeo 1.0 Core) por
1.8.8