Adding includes now needed by ROOT
[u/mrichter/AliRoot.git] / EVE / Reve / ZTrans.cxx
CommitLineData
76082cd6 1// $Header$
2
3// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
4// This file is part of GLED, released under GNU General Public License version 2.
5// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.
6
7//______________________________________________________________________
8// ZTrans
9//
10// ZTrans is a 4x4 transformation matrix for homogeneous coordinates
11// stored internaly in a column-major order to allow direct usage by
12// GL. The element type is Double32_t as statically the floats would
13// be precise enough but continuous operations on the matrix must
14// retain precision of column vectors.
15//
16// Cartan angles in mA[1-3] (+z, -y, +x) are stored for backward
17// compatibility and will probably be removed soon.
18//
19// Direct element access (first two should be used with care):
20// operator[i] direct access to elements, i:0->15
21// CM(i,j) element 4*j + i; i,j:0->3 { CM ~ c-matrix }
22// operator(i,j) element 4*(j-1) + i - 1 i,j:1->4
23//
24// Column-vector access:
25// USet Get/SetBaseVec(), Get/SetPos() and Arr[XYZT]() methods.
26//
27// For all methods taking the matrix indices:
28// 1->X, 2->Y, 3->Z; 4->Position (if applicable). 0 reserved for time.
29//
30// Shorthands in method-names:
31// LF ~ LocalFrame; PF ~ ParentFrame; IP ~ InPlace
32
33#include "ZTrans.h"
34#include "Reve.h"
35#include <TMath.h>
0b28fd57 36#include <TClass.h>
76082cd6 37
38#include <ctype.h>
39
40#define F00 0
41#define F01 4
42#define F02 8
43#define F03 12
44
45#define F10 1
46#define F11 5
47#define F12 9
48#define F13 13
49
50#define F20 2
51#define F21 6
52#define F22 10
53#define F23 14
54
55#define F30 3
56#define F31 7
57#define F32 11
58#define F33 15
59
60using namespace Reve;
61
62ClassImp(ZTrans)
63
64/**************************************************************************/
65
3c67f72c 66ZTrans::ZTrans() :
67 TObject(),
68 mA1(0), mA2(0), mA3(0), bAsOK(kFALSE),
69 fUseTrans (kTRUE),
70 fEditTrans(kFALSE)
71{
72 UnitTrans();
73}
76082cd6 74
3c67f72c 75ZTrans::ZTrans(const ZTrans& t) :
76 TObject(),
77 mA1(t.mA1), mA2(t.mA2), mA3(t.mA3), bAsOK(t.bAsOK),
78 fUseTrans (t.fUseTrans),
79 fEditTrans(t.fEditTrans)
80{
81 SetTrans(t, kFALSE);
82}
76082cd6 83
84/**************************************************************************/
85
86void ZTrans::UnitTrans()
87{
88 // Reset matrix to unity.
89
90 memset(M, 0, 16*sizeof(Double_t));
91 M[F00] = M[F11] = M[F22] = M[F33] = 1;
92 mA1 = mA2 = mA3 = 0;
3c67f72c 93 bAsOK = kTRUE;
76082cd6 94}
95
96void ZTrans::UnitRot()
97{
98 // Reset rotation part of the matrix to unity.
99
100 memset(M, 0, 12*sizeof(Double_t));
101 M[F00] = M[F11] = M[F22] = 1;
102 mA1 = mA2 = mA3 = 0;
3c67f72c 103 bAsOK = kTRUE;
76082cd6 104}
105
3c67f72c 106void ZTrans::SetTrans(const ZTrans& t, Bool_t copyAngles)
76082cd6 107{
108 memcpy(M, t.M, sizeof(M));
3c67f72c 109 if (copyAngles && t.bAsOK) {
110 bAsOK = kTRUE;
111 mA1 = t.mA1; mA2 = t.mA2; mA3 = t.mA3;
112 } else {
113 bAsOK = kFALSE;
114 }
76082cd6 115}
116
76082cd6 117void ZTrans::SetupRotation(Int_t i, Int_t j, Double_t f)
118{
119 // Setup the matrix as an elementary rotation.
120 // Optimized versions of left/right multiplication with an elementary
121 // rotation matrix are implemented in RotatePF/RotateLF.
122 // Expects identity matrix.
123
124 if(i == j) return;
125 ZTrans& M = *this;
126 M(i,i) = M(j,j) = TMath::Cos(f);
127 Double_t s = TMath::Sin(f);
128 M(i,j) = -s; M(j,i) = s;
3c67f72c 129 bAsOK = kFALSE;
76082cd6 130}
131
132/**************************************************************************/
133
134// OrtoNorm3 and Invert are near the bottom.
135
136/**************************************************************************/
137
138void ZTrans::MultLeft(const ZTrans& t)
139{
140 Double_t B[4];
141 Double_t* C = M;
142 for(int c=0; c<4; ++c, C+=4) {
143 const Double_t* T = t.M;
144 for(int r=0; r<4; ++r, ++T)
145 B[r] = T[0]*C[0] + T[4]*C[1] + T[8]*C[2] + T[12]*C[3];
146 C[0] = B[0]; C[1] = B[1]; C[2] = B[2]; C[3] = B[3];
147 }
3c67f72c 148 bAsOK = kFALSE;
76082cd6 149}
150
151void ZTrans::MultRight(const ZTrans& t)
152{
153 Double_t B[4];
154 Double_t* C = M;
155 for(int r=0; r<4; ++r, ++C) {
156 const Double_t* T = t.M;
157 for(int c=0; c<4; ++c, T+=4)
158 B[c] = C[0]*T[0] + C[4]*T[1] + C[8]*T[2] + C[12]*T[3];
159 C[0] = B[0]; C[4] = B[1]; C[8] = B[2]; C[12] = B[3];
160 }
3c67f72c 161 bAsOK = kFALSE;
76082cd6 162}
163
164ZTrans ZTrans::operator*(const ZTrans& t)
165{
166 ZTrans b(*this);
167 b.MultRight(t);
168 return b;
169}
170
171/**************************************************************************/
172// Move & Rotate
173/**************************************************************************/
174
175void ZTrans::MoveLF(Int_t ai, Double_t amount)
176{
177 const Double_t *C = M + 4*--ai;
178 M[F03] += amount*C[0]; M[F13] += amount*C[1]; M[F23] += amount*C[2];
179}
180
181void ZTrans::Move3LF(Double_t x, Double_t y, Double_t z)
182{
183 M[F03] += x*M[0] + y*M[4] + z*M[8];
184 M[F13] += x*M[1] + y*M[5] + z*M[9];
185 M[F23] += x*M[2] + y*M[6] + z*M[10];
186}
187
188void ZTrans::RotateLF(Int_t i1, Int_t i2, Double_t amount)
189{
190 // Rotate in local frame. Does optimised version of MultRight.
191
192 if(i1 == i2) return;
193 // Algorithm: ZTrans a; a.SetupRotation(i1, i2, amount); MultRight(a);
194 // Optimized version:
195 const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
196 Double_t b1, b2;
197 Double_t* C = M;
198 --i1 <<= 2; --i2 <<= 2; // column major
199 for(int r=0; r<4; ++r, ++C) {
200 b1 = cos*C[i1] + sin*C[i2];
201 b2 = cos*C[i2] - sin*C[i1];
202 C[i1] = b1; C[i2] = b2;
203 }
3c67f72c 204 bAsOK = kFALSE;
76082cd6 205}
206
207/**************************************************************************/
208
209void ZTrans::MovePF(Int_t ai, Double_t amount)
210{
211 M[F03 + --ai] += amount;
212}
213
214void ZTrans::Move3PF(Double_t x, Double_t y, Double_t z)
215{
216 M[F03] += x;
217 M[F13] += y;
218 M[F23] += z;
219}
220
221void ZTrans::RotatePF(Int_t i1, Int_t i2, Double_t amount)
222{
223 // Rotate in parent frame. Does optimised version of MultLeft.
224
225 if(i1 == i2) return;
226 // Algorithm: ZTrans a; a.SetupRotation(i1, i2, amount); MultLeft(a);
227
228 // Optimized version:
229 const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
230 Double_t b1, b2;
231 Double_t* C = M;
232 --i1; --i2;
233 for(int c=0; c<4; ++c, C+=4) {
234 b1 = cos*C[i1] - sin*C[i2];
235 b2 = cos*C[i2] + sin*C[i1];
236 C[i1] = b1; C[i2] = b2;
237 }
3c67f72c 238 bAsOK = kFALSE;
76082cd6 239}
240
241/**************************************************************************/
242
243void ZTrans::Move(const ZTrans& a, Int_t ai, Double_t amount)
244{
245 const Double_t* A = a.M + 4*--ai;
246 M[F03] += amount*A[0];
247 M[F13] += amount*A[1];
248 M[F23] += amount*A[2];
249}
250
251void ZTrans::Move3(const ZTrans& a, Double_t x, Double_t y, Double_t z)
252{
253 const Double_t* A = a.M;
254 M[F03] += x*A[F00] + y*A[F01] + z*A[F02];
255 M[F13] += x*A[F10] + y*A[F11] + z*A[F12];
256 M[F23] += x*A[F20] + y*A[F21] + z*A[F22];
257}
258
259void ZTrans::Rotate(const ZTrans& a, Int_t i1, Int_t i2, Double_t amount)
260{
261 if(i1 == i2) return;
262 ZTrans X(a);
263 X.Invert();
264 MultLeft(X);
265 RotatePF(i1, i2, amount);
266 MultLeft(a);
3c67f72c 267 bAsOK = kFALSE;
76082cd6 268}
269
270/**************************************************************************/
271// Base-vector interface
272/**************************************************************************/
273
274void ZTrans::SetBaseVec(Int_t b, Double_t x, Double_t y, Double_t z)
275{
276 Double_t* C = M + 4*--b;
277 C[0] = x; C[1] = y; C[2] = z;
3c67f72c 278 bAsOK = kFALSE;
76082cd6 279}
280
281void ZTrans::SetBaseVec(Int_t b, const TVector3& v)
282{
283 Double_t* C = M + 4*--b;
284 v.GetXYZ(C);
3c67f72c 285 bAsOK = kFALSE;
76082cd6 286}
287
288TVector3 ZTrans::GetBaseVec(Int_t b) const
289{ return TVector3(&M[4*--b]); }
290
291void ZTrans::GetBaseVec(Int_t b, TVector3& v) const
292{
293 const Double_t* C = M + 4*--b;
294 v.SetXYZ(C[0], C[1], C[2]);
295}
296
297/**************************************************************************/
298// Position interface
299/**************************************************************************/
300
301void ZTrans::SetPos(Double_t x, Double_t y, Double_t z)
302{ M[F03] = x; M[F13] = y; M[F23] = z; }
303
304void ZTrans::SetPos(Double_t* x)
305{ M[F03] = x[0]; M[F13] = x[1]; M[F23] = x[2]; }
306
307void ZTrans::SetPos(const ZTrans& t)
308{
309 const Double_t* T = t.M;
310 M[F03] = T[F03]; M[F13] = T[F13]; M[F23] = T[F23];
311}
312
313void ZTrans::GetPos(Double_t& x, Double_t& y, Double_t& z) const
314{ x = M[F03]; y = M[F13]; z = M[F23]; }
315
316void ZTrans::GetPos(Double_t* x) const
317{ x[0] = M[F03]; x[1] = M[F13]; x[2] = M[F23]; }
318
319void ZTrans::GetPos(TVector3& v) const
320{ v.SetXYZ(M[F03], M[F13], M[F23]); }
321
322TVector3 ZTrans::GetPos() const
323{ return TVector3(M[F03], M[F13], M[F23]); }
324
325/**************************************************************************/
326// Cardan angle interface
327/**************************************************************************/
328
329namespace {
330 inline void clamp_angle(Float_t& a) {
331 while(a < -TMath::TwoPi()) a += TMath::TwoPi();
332 while(a > TMath::TwoPi()) a -= TMath::TwoPi();
333 }
334}
335
336void ZTrans::SetRotByAngles(Float_t a1, Float_t a2, Float_t a3)
337{
338 // Sets Rotation part as given by angles:
339 // a1 around z, -a2 around y, a3 around x
340 clamp_angle(a1); clamp_angle(a2); clamp_angle(a3);
341
342 Double_t A, B, C, D, E, F;
343 A = TMath::Cos(a3); B = TMath::Sin(a3);
344 C = TMath::Cos(a2); D = TMath::Sin(a2); // should be -sin(a2) for positive direction
345 E = TMath::Cos(a1); F = TMath::Sin(a1);
346 Double_t AD = A*D, BD = B*D;
347
348 M[F00] = C*E; M[F01] = -BD*E - A*F; M[F02] = -AD*E + B*F;
349 M[F10] = C*F; M[F11] = -BD*F + A*E; M[F12] = -AD*F - B*E;
350 M[F20] = D; M[F21] = B*C; M[F22] = A*C;
351
352 mA1 = a1; mA2 = a2; mA3 = a3;
353 bAsOK = true;
354}
355
356void ZTrans::SetRotByAnyAngles(Float_t a1, Float_t a2, Float_t a3,
357 const Text_t* pat)
358{
359 // Sets Rotation part as given by angles a1, a1, a3 and pattern pat.
360 // Pattern consists of "XxYyZz" characters.
361 // eg: x means rotate about x axis, X means rotate in negative direction
362 // xYz -> R_x(a3) * R_y(-a2) * R_z(a1); (standard Gled representation)
363 // Note that angles and pattern elements have inversed order!
364 //
365 // Implements Eulerian/Cardanian angles in a uniform way.
366
367 int n = strspn(pat, "XxYyZz"); if(n > 3) n = 3;
368 // Build Trans ... assign ...
369 Float_t a[] = { a3, a2, a1 };
370 UnitRot();
371 for(int i=0; i<n; i++) {
372 if(isupper(pat[i])) a[i] = -a[i];
373 switch(pat[i]) {
374 case 'x': case 'X': RotateLF(2, 3, a[i]); break;
375 case 'y': case 'Y': RotateLF(3, 1, a[i]); break;
376 case 'z': case 'Z': RotateLF(1, 2, a[i]); break;
377 }
378 }
3c67f72c 379 bAsOK = kFALSE;
76082cd6 380}
381
382void ZTrans::GetRotAngles(Float_t* x) const
383{
384 // Get Cardan rotation angles (pattern xYz above).
385
386 if(!bAsOK) {
387 Double_t sx, sy, sz;
388 GetScale(sx, sy, sz);
389 Double_t d = M[F20]/sx;
390 if(d>1) d=1; else if(d<-1) d=-1; // Fix numerical errors
391 mA2 = TMath::ASin(d);
392 Double_t C = TMath::Cos(mA2);
393 if(TMath::Abs(C) > 8.7e-6) {
394 mA1 = TMath::ATan2(M[F10], M[F00]);
395 mA3 = TMath::ATan2(M[F21]/sy, M[F22]/sz);
396 } else {
397 mA1 = TMath::ATan2(M[F10]/sx, M[F11]/sy);
398 mA3 = 0;
399 }
400 bAsOK = true;
401 }
402 x[0] = mA1; x[1] = mA2; x[2] = mA3;
403}
404
405/**************************************************************************/
406// Scaling
407/**************************************************************************/
408
409void ZTrans::Scale(Double_t sx, Double_t sy, Double_t sz)
410{
411 M[F00] *= sx; M[F10] *= sx; M[F20] *= sx;
412 M[F01] *= sy; M[F11] *= sy; M[F21] *= sy;
413 M[F02] *= sz; M[F12] *= sz; M[F22] *= sz;
414}
415
416void ZTrans::GetScale(Double_t& sx, Double_t& sy, Double_t& sz) const
417{
418 sx = TMath::Sqrt( M[F00]*M[F00] + M[F10]*M[F10] + M[F20]*M[F20] );
419 sy = TMath::Sqrt( M[F01]*M[F01] + M[F11]*M[F11] + M[F21]*M[F21] );
420 sz = TMath::Sqrt( M[F02]*M[F02] + M[F12]*M[F12] + M[F22]*M[F22] );
421}
422
423void ZTrans::Unscale(Double_t& sx, Double_t& sy, Double_t& sz)
424{
425 GetScale(sx, sy, sz);
426 M[F00] /= sx; M[F10] /= sx; M[F20] /= sx;
427 M[F01] /= sy; M[F11] /= sy; M[F21] /= sy;
428 M[F02] /= sz; M[F12] /= sz; M[F22] /= sz;
429}
430
431Double_t ZTrans::Unscale()
432{
433 Double_t sx, sy, sz;
434 Unscale(sx, sy, sz);
435 return (sx + sy + sz)/3;
436}
437
438/**************************************************************************/
439// Operations on vectors
440/**************************************************************************/
441
442void ZTrans::MultiplyIP(TVector3& v, Double_t w) const
443{
444 v.SetXYZ(M[F00]*v.x() + M[F01]*v.y() + M[F02]*v.z() + M[F03]*w,
445 M[F10]*v.x() + M[F11]*v.y() + M[F12]*v.z() + M[F13]*w,
446 M[F20]*v.x() + M[F21]*v.y() + M[F22]*v.z() + M[F23]*w);
447}
448
449TVector3 ZTrans::Multiply(const TVector3& v, Double_t w) const
450{
451 return TVector3(M[F00]*v.x() + M[F01]*v.y() + M[F02]*v.z() + M[F03]*w,
452 M[F10]*v.x() + M[F11]*v.y() + M[F12]*v.z() + M[F13]*w,
453 M[F20]*v.x() + M[F21]*v.y() + M[F22]*v.z() + M[F23]*w);
454}
455
456void ZTrans::RotateIP(TVector3& v) const
457{
458 v.SetXYZ(M[F00]*v.x() + M[F01]*v.y() + M[F02]*v.z(),
459 M[F10]*v.x() + M[F11]*v.y() + M[F12]*v.z(),
460 M[F20]*v.x() + M[F21]*v.y() + M[F22]*v.z());
461}
462
463TVector3 ZTrans::Rotate(const TVector3& v) const
464{
465 return TVector3(M[F00]*v.x() + M[F01]*v.y() + M[F02]*v.z(),
466 M[F10]*v.x() + M[F11]*v.y() + M[F12]*v.z(),
467 M[F20]*v.x() + M[F21]*v.y() + M[F22]*v.z());
468}
469
470/**************************************************************************/
471// Normalization, ortogonalization
472/**************************************************************************/
473
474Double_t ZTrans::norm3_column(Int_t col)
475{
476 Double_t* C = M + 4*--col;
477 const Double_t l = TMath::Sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
478 C[0] /= l; C[1] /= l; C[2] /= l;
479 return l;
480}
481
482Double_t ZTrans::orto3_column(Int_t col, Int_t ref)
483{
484 Double_t* C = M + 4*--col;
485 Double_t* R = M + 4*--ref;
486 const Double_t dp = C[0]*R[0] + C[1]*R[1] + C[2]*R[2];
487 C[0] -= R[0]*dp; C[1] -= R[1]*dp; C[2] -= R[2]*dp;
488 return dp;
489}
490
491void ZTrans::OrtoNorm3()
492{
493 norm3_column(1);
494 orto3_column(2,1); norm3_column(2);
495 M[F02] = M[F10]*M[F21] - M[F11]*M[F20];
496 M[F12] = M[F20]*M[F01] - M[F21]*M[F00];
497 M[F22] = M[F00]*M[F11] - M[F01]*M[F10];
498 // cross-product faster.
499 // orto3_column(3,1); orto3_column(3,2); norm3_column(3);
500}
501
502/**************************************************************************/
503// Inversion
504/**************************************************************************/
505
506Double_t ZTrans::Invert()
507{
508 // Copied from ROOT's TMatrixFCramerInv.
509
510 static const Exc_t _eh("ZTrans::Invert ");
511
512 // Find all NECESSARY 2x2 dets: (18 of them)
513 const Double_t det2_12_01 = M[F10]*M[F21] - M[F11]*M[F20];
514 const Double_t det2_12_02 = M[F10]*M[F22] - M[F12]*M[F20];
515 const Double_t det2_12_03 = M[F10]*M[F23] - M[F13]*M[F20];
516 const Double_t det2_12_13 = M[F11]*M[F23] - M[F13]*M[F21];
517 const Double_t det2_12_23 = M[F12]*M[F23] - M[F13]*M[F22];
518 const Double_t det2_12_12 = M[F11]*M[F22] - M[F12]*M[F21];
519 const Double_t det2_13_01 = M[F10]*M[F31] - M[F11]*M[F30];
520 const Double_t det2_13_02 = M[F10]*M[F32] - M[F12]*M[F30];
521 const Double_t det2_13_03 = M[F10]*M[F33] - M[F13]*M[F30];
522 const Double_t det2_13_12 = M[F11]*M[F32] - M[F12]*M[F31];
523 const Double_t det2_13_13 = M[F11]*M[F33] - M[F13]*M[F31];
524 const Double_t det2_13_23 = M[F12]*M[F33] - M[F13]*M[F32];
525 const Double_t det2_23_01 = M[F20]*M[F31] - M[F21]*M[F30];
526 const Double_t det2_23_02 = M[F20]*M[F32] - M[F22]*M[F30];
527 const Double_t det2_23_03 = M[F20]*M[F33] - M[F23]*M[F30];
528 const Double_t det2_23_12 = M[F21]*M[F32] - M[F22]*M[F31];
529 const Double_t det2_23_13 = M[F21]*M[F33] - M[F23]*M[F31];
530 const Double_t det2_23_23 = M[F22]*M[F33] - M[F23]*M[F32];
531
532 // Find all NECESSARY 3x3 dets: (16 of them)
533 const Double_t det3_012_012 = M[F00]*det2_12_12 - M[F01]*det2_12_02 + M[F02]*det2_12_01;
534 const Double_t det3_012_013 = M[F00]*det2_12_13 - M[F01]*det2_12_03 + M[F03]*det2_12_01;
535 const Double_t det3_012_023 = M[F00]*det2_12_23 - M[F02]*det2_12_03 + M[F03]*det2_12_02;
536 const Double_t det3_012_123 = M[F01]*det2_12_23 - M[F02]*det2_12_13 + M[F03]*det2_12_12;
537 const Double_t det3_013_012 = M[F00]*det2_13_12 - M[F01]*det2_13_02 + M[F02]*det2_13_01;
538 const Double_t det3_013_013 = M[F00]*det2_13_13 - M[F01]*det2_13_03 + M[F03]*det2_13_01;
539 const Double_t det3_013_023 = M[F00]*det2_13_23 - M[F02]*det2_13_03 + M[F03]*det2_13_02;
540 const Double_t det3_013_123 = M[F01]*det2_13_23 - M[F02]*det2_13_13 + M[F03]*det2_13_12;
541 const Double_t det3_023_012 = M[F00]*det2_23_12 - M[F01]*det2_23_02 + M[F02]*det2_23_01;
542 const Double_t det3_023_013 = M[F00]*det2_23_13 - M[F01]*det2_23_03 + M[F03]*det2_23_01;
543 const Double_t det3_023_023 = M[F00]*det2_23_23 - M[F02]*det2_23_03 + M[F03]*det2_23_02;
544 const Double_t det3_023_123 = M[F01]*det2_23_23 - M[F02]*det2_23_13 + M[F03]*det2_23_12;
545 const Double_t det3_123_012 = M[F10]*det2_23_12 - M[F11]*det2_23_02 + M[F12]*det2_23_01;
546 const Double_t det3_123_013 = M[F10]*det2_23_13 - M[F11]*det2_23_03 + M[F13]*det2_23_01;
547 const Double_t det3_123_023 = M[F10]*det2_23_23 - M[F12]*det2_23_03 + M[F13]*det2_23_02;
548 const Double_t det3_123_123 = M[F11]*det2_23_23 - M[F12]*det2_23_13 + M[F13]*det2_23_12;
549
550 // Find the 4x4 det:
551 const Double_t det = M[F00]*det3_123_123 - M[F01]*det3_123_023 +
552 M[F02]*det3_123_013 - M[F03]*det3_123_012;
553
554 if(det == 0) {
555 throw(_eh + "matrix is singular.");
556 }
557
558 const Double_t oneOverDet = 1.0/det;
559 const Double_t mn1OverDet = - oneOverDet;
560
561 M[F00] = det3_123_123 * oneOverDet;
562 M[F01] = det3_023_123 * mn1OverDet;
563 M[F02] = det3_013_123 * oneOverDet;
564 M[F03] = det3_012_123 * mn1OverDet;
565
566 M[F10] = det3_123_023 * mn1OverDet;
567 M[F11] = det3_023_023 * oneOverDet;
568 M[F12] = det3_013_023 * mn1OverDet;
569 M[F13] = det3_012_023 * oneOverDet;
570
571 M[F20] = det3_123_013 * oneOverDet;
572 M[F21] = det3_023_013 * mn1OverDet;
573 M[F22] = det3_013_013 * oneOverDet;
574 M[F23] = det3_012_013 * mn1OverDet;
575
576 M[F30] = det3_123_012 * mn1OverDet;
577 M[F31] = det3_023_012 * oneOverDet;
578 M[F32] = det3_013_012 * mn1OverDet;
579 M[F33] = det3_012_012 * oneOverDet;
580
3c67f72c 581 bAsOK = kFALSE;
76082cd6 582 return det;
583}
584
585/**************************************************************************/
586
587void ZTrans::Streamer(TBuffer &R__b)
588{
589 // Stream an object of class ZTrans.
590
591 if (R__b.IsReading()) {
592 ZTrans::Class()->ReadBuffer(R__b, this);
3c67f72c 593 bAsOK = kFALSE;
76082cd6 594 } else {
595 ZTrans::Class()->WriteBuffer(R__b, this);
596 }
597}
598
599/**************************************************************************/
600/**************************************************************************/
601
602void ZTrans::Print(Option_t* /*option*/) const
603{
604 const Double_t* C = M;
605 for(Int_t i=0; i<4; ++i, ++C)
606 printf("%8.3f %8.3f %8.3f | %8.3f\n", C[0], C[4], C[8], C[12]);
607}
608
609#include <iomanip>
610
611ostream& Reve::operator<<(ostream& s, const ZTrans& t) {
612 s.setf(std::ios::fixed, std::ios::floatfield);
613 s.precision(3);
614 for(Int_t i=1; i<=4; i++)
615 for(Int_t j=1; j<=4; j++)
616 s << t(i,j) << ((j==4) ? "\n" : "\t");
617 return s;
618}
619
620/**************************************************************************/
621// Reve stuff
622/**************************************************************************/
623
624#include <TGeoMatrix.h>
625#include <TBuffer3D.h>
626
627void ZTrans::SetFrom(Double_t* carr)
628{
629 fUseTrans = kTRUE;
630 memcpy(M, carr, 16*sizeof(Double_t));
3c67f72c 631 bAsOK = kFALSE;
76082cd6 632}
633
634void ZTrans::SetFrom(const TGeoMatrix& mat)
635{
636 fUseTrans = kTRUE;
637 const Double_t *r = mat.GetRotationMatrix();
638 const Double_t *t = mat.GetTranslation();
639 const Double_t *s = mat.GetScale();
640 Double_t *m = M;
641 m[0] = r[0]*s[0]; m[1] = r[3]*s[0]; m[2] = r[6]*s[0]; m[3] = 0; m += 4;
642 m[0] = r[1]*s[1]; m[1] = r[4]*s[1]; m[2] = r[7]*s[1]; m[3] = 0; m += 4;
643 m[0] = r[2]*s[2]; m[1] = r[5]*s[2]; m[2] = r[8]*s[2]; m[3] = 0; m += 4;
644 m[0] = t[0]; m[1] = t[1]; m[2] = t[2]; m[3] = 1;
3c67f72c 645 bAsOK = kFALSE;
76082cd6 646}
647
648void ZTrans::SetBuffer3D(TBuffer3D& buff)
649{
650 buff.fLocalFrame = fUseTrans;
651 if (fUseTrans)
652 memcpy(buff.fLocalMaster, M, 16*sizeof(Double_t));
653}
654
655Bool_t ZTrans::IsScale(Double_t low, Double_t high) const
656{
657 // Test if the transformation is a scale.
658 // To be used by ROOT TGLObject descendants that potentially need to
659 // use GL_NORMALIZE.
660 // The low/high limits are expected to be squares of acutal limits.
661 //
662 // Ideally this should be done by the TGLViewer [but is not].
663
664 if (!fUseTrans) return kFALSE;
665 Double_t s;
666 s = M[F00]*M[F00] + M[F10]*M[F10] + M[F20]*M[F20];
667 if (s < low || s > high) return kTRUE;
668 s = M[F01]*M[F01] + M[F11]*M[F11] + M[F21]*M[F21];
669 if (s < low || s > high) return kTRUE;
670 s = M[F02]*M[F02] + M[F12]*M[F12] + M[F22]*M[F22];
671 if (s < low || s > high) return kTRUE;
672 return kFALSE;
673}