ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/LJMet/MultivariateAnalysis/interface/TMBVector3.h
Revision: 1.1
Committed: Tue Nov 11 23:01:21 2008 UTC (16 years, 5 months ago) by kukartse
Content type: text/plain
Branch: MAIN
CVS Tags: V00-03-01, ZMorph_BASE_20100408, gak040610_morphing, V00-02-02, gak011410, gak010310, ejterm2010_25nov2009, V00-02-01, V00-02-00, gak112409, CMSSW_22X_branch_base, segala101609, V00-01-15, V00-01-14, V00-01-13, V00-01-12, V00-01-11, V00-01-10, gak031009, gak030509, gak022309, gak021209, gak040209, gak012809, V00-01-09, V00-01-08, V00-01-07, V00-01-06, V00-01-05, V00-01-04, V00-00-07, V00-00-06, V00-00-05, V00-00-04, V00-01-03, V00-00-02, V00-00-01, HEAD
Branch point for: ZMorph-V00-03-01, CMSSW_22X_branch
Log Message:
initial creation of a package for LJMET multivariate analysis

File Contents

# User Rev Content
1 kukartse 1.1 #ifndef INCLUDE_TMBVECTOR3
2     #define INCLUDE_TMBVECTOR3
3    
4     #include "TMath.h"
5     #include "TError.h"
6     #include "TVector2.h"
7     #include "TMatrix.h"
8     #include "TRotation.h"
9    
10     /*! \brief
11     The Physics Vector package
12    
13     The Physics Vector package consists of five classes:
14     - TVector2
15     - TVector3
16     - TRotation
17     - TLorentzVector
18     - TLorentzRotation
19     It is a combination of CLHEPs Vector package written by
20     Leif Lonnblad, Andreas Nilsson and Evgueni Tcherniaev
21     and a ROOT package written by Pasha Murat.
22     for CLHEP see: http://wwwinfo.cern.ch/asd/lhc++/clhep/
23    
24     \ingroup reco
25    
26     <H2>
27     TVector3</H2>
28     <TT>TVector3</TT> is a general three vector class, which can be used for
29     the description of different vectors in 3D.
30     <H3>
31     Declaration / Access to the components</H3>
32     <TT>TVector3</TT> has been implemented as a vector of three <TT>Double_t</TT>
33     variables, representing the cartesian coordinates. By default all components
34     are initialized to zero:
35    
36     <P><TT>&nbsp; TVector3 v1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //
37     v1 = (0,0,0)</TT>
38     <BR><TT>&nbsp; TVector3 v2(1);&nbsp;&nbsp;&nbsp;&nbsp; // v2 = (1,0,0)</TT>
39     <BR><TT>&nbsp; TVector3 v3(1,2,3); // v3 = (1,2,3)</TT>
40     <BR><TT>&nbsp; TVector3 v4(v2);&nbsp;&nbsp;&nbsp; // v4 = v2</TT>
41    
42     <P>It is also possible (but not recommended) to initialize a <TT>TVector3</TT>
43     with a <TT>Double_t</TT> or <TT>Float_t</TT> C array.
44    
45     <P>You can get the basic components either by name or by index using <TT>operator()</TT>:
46    
47     <P><TT>&nbsp; xx = v1.X();&nbsp;&nbsp;&nbsp; or&nbsp;&nbsp;&nbsp; xx =
48     v1(0);</TT>
49     <BR><TT>&nbsp; yy = v1.Y();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
50     yy = v1(1);</TT>
51     <BR><TT>&nbsp; zz = v1.Z();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
52     zz = v1(2);</TT>
53    
54     <P>The memberfunctions <TT>SetX()</TT>, <TT>SetY()</TT>, <TT>SetZ()</TT>
55     and<TT> SetXYZ()</TT> allow to set the components:
56    
57     <P><TT>&nbsp; v1.SetX(1.); v1.SetY(2.); v1.SetZ(3.);</TT>
58     <BR><TT>&nbsp; v1.SetXYZ(1.,2.,3.);</TT>
59     <BR>&nbsp;
60     <H3>
61     Noncartesian coordinates</H3>
62     To get information on the <TT>TVector3</TT> in spherical (rho,phi,theta)
63     or cylindrical (z,r,theta) coordinates, the
64     <BR>the member functions <TT>Mag3()</TT> (=magnitude=rho in spherical coordinates),
65     <TT>Mag32()</TT>, <TT>Theta()</TT>, <TT>CosTheta()</TT>, <TT>Phi()</TT>,
66     <TT>Perp()</TT> (the transverse component=r in cylindrical coordinates),
67     <TT>Perp2()</TT> can be used:
68    
69     <P><TT>&nbsp; Double_t m&nbsp; = v.Mag3();&nbsp;&nbsp;&nbsp; // get magnitude
70     (=rho=Sqrt(x*x+y*y+z*z)))</TT>
71     <BR><TT>&nbsp; Double_t m2 = v.Mag32();&nbsp;&nbsp; // get magnitude squared</TT>
72     <BR><TT>&nbsp; Double_t t&nbsp; = v.Theta();&nbsp; // get polar angle</TT>
73     <BR><TT>&nbsp; Double_t ct = v.CosTheta();// get cos of theta</TT>
74     <BR><TT>&nbsp; Double_t p&nbsp; = v.Phi();&nbsp;&nbsp;&nbsp; // get azimuth angle</TT>
75     <BR><TT>&nbsp; Double_t pp = v.Perp();&nbsp;&nbsp; // get transverse component</TT>
76     <BR><TT>&nbsp; Double_t pp2= v.Perp2();&nbsp; // get transvers component
77     squared</TT>
78    
79     <P>It is also possible to get the transverse component with respect to
80     another vector:
81    
82     <P><TT>&nbsp; Double_t ppv1 = v.Perp(v1);</TT>
83     <BR><TT>&nbsp; Double_t pp2v1 = v.Perp2(v1);</TT>
84    
85     <P>The pseudorapiditiy ( eta=-ln (tan (phi/2)) ) can be get by <TT>Eta()</TT>
86     or <TT>PseudoRapidity()</TT>:
87     <BR>&nbsp;
88     <BR><TT>&nbsp; Double_t eta = v.PseudoRapidity();</TT>
89    
90     <P>There are set functions to change one of the noncartesian coordinates:
91    
92     <P><TT>&nbsp; v.SetTheta(.5); // keeping rho and phi</TT>
93     <BR><TT>&nbsp; v.SetPhi(.8);&nbsp;&nbsp; // keeping rho and theta</TT>
94     <BR><TT>&nbsp; v.SetMag3(10.);&nbsp; // keeping theta and phi</TT>
95     <BR><TT>&nbsp; v.SetPerp(3.);&nbsp; // keeping z and phi</TT>
96     <BR>&nbsp;
97     <H3>
98     Arithmetic / Comparison</H3>
99     The <TT>TVector3</TT> class provides the operators to add, subtract, scale and compare
100     vectors:
101    
102     <P><TT>&nbsp; v3&nbsp; = -v1;</TT>
103     <BR><TT>&nbsp; v1&nbsp; = v2+v3;</TT>
104     <BR><TT>&nbsp; v1 += v3;</TT>
105     <BR><TT>&nbsp; v1&nbsp; = v1 - v3</TT>
106     <BR><TT>&nbsp; v1 -= v3;</TT>
107     <BR><TT>&nbsp; v1 *= 10;</TT>
108     <BR><TT>&nbsp; v1&nbsp; = 5*v2;</TT>
109    
110     <P><TT>&nbsp; if(v1==v2) {...}</TT>
111     <BR><TT>&nbsp; if(v1!=v2) {...}</TT>
112     <BR>&nbsp;
113     <H3>
114     Related Vectors</H3>
115     <TT>&nbsp; v2 = v1.Unit();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get unit
116     vector parallel to v1</TT>
117     <BR><TT>&nbsp; v2 = v1.Orthogonal(); // get vector orthogonal to v1</TT>
118     <H3>
119     Scalar and vector products</H3>
120     <TT>&nbsp; s = v1.Dot(v2);&nbsp;&nbsp; // scalar product</TT>
121     <BR><TT>&nbsp; s = v1 * v2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // scalar product</TT>
122     <BR><TT>&nbsp; v = v1.Cross(v2); // vector product</TT>
123     <H3>
124     &nbsp;Angle between two vectors</H3>
125     <TT>&nbsp; Double_t a = v1.Angle(v2);</TT>
126     <H3>
127     Rotations</H3>
128    
129     <H5>
130     Rotation around axes</H5>
131     <TT>&nbsp; v.RotateX(.5);</TT>
132     <BR><TT>&nbsp; v.RotateY(TMath::Pi());</TT>
133     <BR><TT>&nbsp; v.RotateZ(angle);</TT>
134     <H5>
135     Rotation around a vector</H5>
136     <TT>&nbsp; v1.Rotate(TMath::Pi()/4, v2); // rotation around v2</TT>
137     <H5>
138     Rotation by TRotation</H5>
139     <TT>TVector3</TT> objects can be rotated by objects of the <TT>TRotation</TT>
140     class using the <TT>Transform()</TT> member functions,
141     <BR>the <TT>operator *=</TT> or the <TT>operator *</TT> of the TRotation
142     class:
143    
144     <P><TT>&nbsp; TRotation m;</TT>
145     <BR><TT>&nbsp; ...</TT>
146     <BR><TT>&nbsp; v1.transform(m);</TT>
147     <BR><TT>&nbsp; v1 = m*v1;</TT>
148     <BR><TT>&nbsp; v1 *= m; // Attention v1 = m*v1</TT>
149     <H5>
150     Transformation from rotated frame</H5>
151     <TT>&nbsp; TVector3 direction = v.Unit()</TT>
152     <BR><TT>&nbsp; v1.RotateUz(direction); // direction must be TVector3 of
153     unit length</TT>
154    
155     <P>transforms v1 from the rotated frame (z' parallel to direction, x' in
156     the theta plane and y' in the xy plane as well as perpendicular to the
157     theta plane) to the (x,y,z) frame.'
158    
159     See copyright statements at end of file.
160    
161     */
162    
163     class TMBVector3 : public TObject {
164     public:
165    
166     TMBVector3(Double_t x = 0.0, Double_t y = 0.0, Double_t z = 0.0):
167     fX(x), fY(y), fZ(z) { /// The constructor.
168     }
169    
170     TMBVector3(const Double_t *a): fX(a[0]), fY(a[1]), fZ(a[2])
171     { /// Constructor from an array
172     }
173    
174     TMBVector3(const Float_t *a): fX(a[0]), fY(a[1]), fZ(a[2])
175     { /// Constructor from an array
176     }
177    
178     TMBVector3(const TMBVector3 &p): TObject(p),
179     fX(p.fX), fY(p.fY), fZ(p.fZ)
180     { /// Copy constructor.
181     }
182    
183     TMBVector3(const TVector3& v): fX(v.X()), fY(v.Y()), fZ(v.Z())
184     {
185     /// conversion constructor from TVector3
186     }
187    
188     virtual ~TMBVector3() {}
189     // Destructor
190    
191     Double_t operator () (int i) const {
192     /// Get components by index.
193     switch(i) {
194     case 0: return fX;
195     case 1: return fY;
196     case 2: return fZ;
197     default: Error("operator()(i)", "bad index (%d) returning &fX",i);
198     }
199     return 0.;
200     }
201    
202     inline Double_t operator [] (int i) const { /// Get components by index.
203     return operator()(i); }
204    
205    
206     Double_t & operator () (int i) {
207     /// Get components by index.
208    
209     switch(i) {
210     case 0: return fX;
211     case 1: return fY;
212     case 2: return fZ;
213     default: Error("operator()(i)", "bad index (%d) returning &fX",i);
214     }
215     return fX;
216     }
217     inline Double_t & operator [] (int i) { /// Set components by index.
218     return operator()(i); }
219    
220     Double_t x() const { /// get X component
221     return fX; }
222     Double_t X() const { /// get X component
223     return x(); }
224     Double_t Px() const { /// get X component
225     return x(); }
226    
227     Double_t y() const { /// get Y component
228     return fY; }
229     Double_t Y() const { /// get Y component
230     return y(); }
231     Double_t Py() const { /// get X component
232     return y(); }
233    
234     Double_t z() const { /// get Y component
235     return fZ; }
236     Double_t Z() const { /// get Z component
237     return z(); }
238     Double_t Pz() const { /// get X component
239     return z(); }
240    
241     void SetX(Double_t a) { /// set X component, see TVector3::SetX()
242     fX=a; }
243     void SetPx(Double_t a) { /// set X component, see TVector3::SetX()
244     SetX(a); }
245     void SetY(Double_t a) { /// set X component, see TVector3::SetY()
246     fY=a; }
247     void SetPy(Double_t a) { /// set X component, see TVector3::SetX()
248     SetY(a); }
249     void SetZ(Double_t a) { /// set X component, see TVector3::SetZ()
250     fZ=a; }
251     void SetPz(Double_t a) { /// set X component, see TVector3::SetX()
252     SetZ(a); }
253     inline void SetXYZ(Double_t x, Double_t y, Double_t z) {
254     /// set all members using Cartesian coordinates
255     fX=x; fY=y; fZ=z; }
256    
257     void SetPtEtaPhi(Double_t pt, Double_t eta, Double_t phi) {
258     /// set all members using |momentum|, eta, and phi
259     Double_t apt = TMath::Abs(pt);
260     Double_t d=TMath::Tan(2.0*TMath::ATan(TMath::Exp(-eta)));
261     if (d==0.)
262     Warning("SetPtEtaPhi", "tan(2*atan(exp(-eta)))==0.! Setting z=0.");
263     SetXYZ(apt*TMath::Cos(phi), apt*TMath::Sin(phi), d==0.?0.:apt/d );
264     }
265     void SetPtThetaPhi(Double_t pt, Double_t theta, Double_t phi) {
266     /// set all members using |momentum|, theta, and phi
267     Double_t apt = TMath::Abs(pt);
268     fX = apt * TMath::Cos(phi);
269     fY = apt * TMath::Sin(phi);
270     Double_t tanTheta = TMath::Tan(theta);
271     if (tanTheta==0.)
272     Warning("SetPtThetaPhi", "tan(theta)==0.! Setting z=0.");
273     fZ = tanTheta ? apt / tanTheta : 0;
274     }
275    
276     inline void GetXYZ(Double_t *carray) const {
277     /// Getters into an arry (no checking of array bounds!)
278     carray[0]=fX; carray[1]=fY; carray[2]=fZ; }
279     inline void GetXYZ(Float_t *carray) const {
280     /// Getters into an arry (no checking of array bounds!)
281     carray[0]=fX; carray[1]=fY; carray[2]=fZ; }
282    
283     Double_t Eta() const { /// get eta (aka pseudo-rapidity)
284     return PseudoRapidity(); }
285     Double_t Theta() const { /// get theta
286     return fX==.0 && fY==.0 && fZ==.0 ? .0 : TMath::ATan2(Perp(),fZ); }
287     Double_t CosTheta() const { /// get cos(Theta)
288     Double_t ptot = Mag3();
289     return ptot == 0.0 ? 1.0 : fZ/ptot;
290     }
291     Double_t Phi() const { /// get phi from 0..2Pi
292     return (fX==.0 && fY==.0 ? .0 : TVector2::Phi_0_2pi(TMath::ATan2(fY,fX))); }
293    
294     Double_t Rho() const { /// get magnitude of momentum ("radius" in spherical coords)
295     return Mag3(); }
296    
297     virtual Double_t Mag32() const {
298     /// The magnitude squared (rho^2 in spherical coordinate system).
299     return fX*fX + fY*fY + fZ*fZ; }
300     virtual Double_t Mag3() const {
301     /// The magnitude (rho in spherical coordinate system).
302     return TMath::Sqrt(Mag32()); }
303     Double_t P() const { /// get |P|
304     return Mag3(); }
305    
306     Double_t DeltaPhi(const TMBVector3 &v) const {
307     /// Get difference in phi, between -pi and pi
308     return TVector2::Phi_mpi_pi(Phi()-v.Phi()); }
309    
310     Double_t DeltaR(const TMBVector3 &v) const {
311     /// Get "distance" dR of v to *this, dR=sqrt(dPhi*dPhi+dEta*dEta)
312     Double_t deta = Eta()-v.Eta();
313     Double_t dphi = TVector2::Phi_mpi_pi(Phi()-v.Phi());
314     return TMath::Sqrt( deta*deta+dphi*dphi );
315     }
316     Double_t DrEtaPhi(const TMBVector3 &lv) const {
317     /// Get "distance" dR of lv to *this, dR=sqrt(dPhi*dPhi+dEta*dEta)
318     return DeltaR(lv); }
319    
320     // TVector2 EtaPhiVector() { /// return TVector2(eta,phi)
321     // return TVector2 (Eta(),Phi()); }
322    
323     Double_t Angle(const TVector3 & q) const { /// Angle wrt. another vector.
324     Double_t ptot2 = Mag32()*q.Mag2();
325     if(ptot2 <= 0.) return .0;
326     Double_t arg = Dot(q)/TMath::Sqrt(ptot2);
327     if(arg > 1.0) arg = 1.0;
328     if(arg < -1.0) arg = -1.0;
329     return TMath::ACos(arg);
330     }
331    
332     void SetPhi(Double_t ph) { /// set phi keeping mag and theta constant
333     Double_t xy = Perp();
334     SetX(xy*TMath::Cos(ph));
335     SetY(xy*TMath::Sin(ph));
336     }
337    
338     inline void SetTheta(Double_t th) { /// Set theta keeping mag and phi constant
339     Double_t ma = Mag3();
340     Double_t ph = Phi();
341     SetX(ma*TMath::Sin(th)*TMath::Cos(ph));
342     SetY(ma*TMath::Sin(th)*TMath::Sin(ph));
343     SetZ(ma*TMath::Cos(th));
344     }
345    
346     inline void SetMag3(Double_t ma) { /// Set magnitude keeping theta and phi constant
347     Double_t factor = Mag3();
348     if (factor == 0) {
349     Warning("SetMag3","zero vector can't be stretched");
350     }else{
351     factor = ma/factor;
352     SetX(fX*factor);
353     SetY(fY*factor);
354     SetZ(fZ*factor);
355     }
356     }
357     inline Double_t Perp2() const {
358     /// The transverse component squared (R^2 in cylindrical coordinate system)
359     return fX*fX + fY*fY; }
360     inline Double_t Pt() const {
361     /// transverse component; projection of 3 vector onto XY plane (R in cylindrical coords)
362     return Perp(); }
363     inline Double_t Perp() const {
364     /// The transverse component (R in cylindrical coordinate system)
365     return TMath::Sqrt(Perp2()); }
366    
367     inline void SetPerp(Double_t r) {
368     /// Set the transverse component keeping phi and z constant.
369     Double_t p = Perp();
370     if (p != 0.0) {
371     fX *= r/p;
372     fY *= r/p;
373     }
374     }
375    
376     inline Double_t Perp2(const TMBVector3 &p) const {
377     /// The transverse component w.r.t. given axis squared.
378     Double_t tot = p.Mag32();
379     Double_t ss = Dot(p);
380     return tot > 0.0 ? Mag32()-ss*ss/tot : Mag32();
381     }
382    
383     inline Double_t Pt(const TMBVector3 &p) const {
384     /// The transverse component w.r.t. given axis.
385     return Perp(p); }
386     inline Double_t Perp(const TMBVector3 &p) const {
387     /// The transverse component w.r.t. given axis.
388     return TMath::Sqrt(Perp2(p)); }
389    
390     inline void SetMag3ThetaPhi(Double_t mag, Double_t theta, Double_t phi) {
391     /// Set all components as magnitude, theta, and phi
392     Double_t amag = TMath::Abs(mag);
393     fX = amag * TMath::Sin(theta) * TMath::Cos(phi);
394     fY = amag * TMath::Sin(theta) * TMath::Sin(phi);
395     fZ = amag * TMath::Cos(theta);
396     }
397    
398     inline TMBVector3 & operator = (const TMBVector3 &p) {
399     /// Assignment.
400     fX = p.fX; fY = p.fY; fZ = p.fZ;
401     return *this;
402     }
403    
404     inline Bool_t operator == (const TMBVector3 &v) const {
405     /// Equality operator. Equal if all components X,Y,Z are equal.
406     return (v.fX==fX && v.fY==fY && v.fZ==fZ); }
407     inline Bool_t operator != (const TMBVector3 &v) const {
408     /// Inequality operator. Not equal if any of X,Y,Z are not equal.
409     return (v.fX!=fX || v.fY!=fY || v.fZ!=fZ); }
410    
411     /// Equivalence operator. True if all components are
412     /// equivalent within machine precision.
413     Bool_t is_equal (const TMBVector3 &v) const;
414    
415     inline TMBVector3 & operator += (const TMBVector3 &p) { /// Addition.
416     fX += p.fX; fY += p.fY; fZ += p.fZ;
417     return *this;
418     }
419    
420     inline TMBVector3 & operator -= (const TMBVector3 &p) { /// Subtraction.
421     fX -= p.fX; fY -= p.fY; fZ -= p.fZ;
422     return *this;
423     }
424    
425     inline TMBVector3 operator - () const { /// Unary minus.
426     return TMBVector3(-fX, -fY, -fZ); }
427    
428     inline TMBVector3 & operator *= (Double_t a) {
429     /// Scaling with real numbers.
430     fX *= a; fY *= a; fZ *= a;
431     return *this;
432     }
433    
434     inline TMBVector3 Unit() const { /// Unit vector parallel to this.
435     Double_t tot = Mag32();
436     TMBVector3 p(fX,fY,fZ);
437     return tot>.0 ? p *= (1.0/TMath::Sqrt(tot)) : p;
438     }
439    
440     inline TMBVector3 Orthogonal() const { /// Vector orthogonal to this.
441     Double_t x = fX < 0.0 ? -fX : fX;
442     Double_t y = fY < 0.0 ? -fY : fY;
443     Double_t z = fZ < 0.0 ? -fZ : fZ;
444     if (x < y)
445     return x<z ? TMBVector3(0,fZ,-fY) : TMBVector3(fY,-fX,0);
446     return y<z ? TMBVector3(-fZ,0,fX) : TMBVector3(fY,-fX,0);
447     }
448    
449     Double_t Dot(const TMBVector3 &p) const { /// Scalar product.
450     return fX*p.fX + fY*p.fY + fZ*p.fZ; }
451    
452     inline TMBVector3 Cross(const TMBVector3 &p) const { /// Cross product
453     return TMBVector3(fY*p.fZ-p.fY*fZ, fZ*p.fX-p.fZ*fX, fX*p.fY-p.fX*fY);
454     }
455    
456     Double_t PseudoRapidity() const {
457     /// Returns the pseudo-rapidity, i.e. -ln(tan(theta/2))
458     double cosTheta = CosTheta();
459     if (cosTheta*cosTheta < 1)
460     return (-0.5* TMath::Log( (1.0-cosTheta)/(1.0+cosTheta) ));
461     Warning("PseudoRapidity","transvers momentum = 0! return +/- 10e10");
462     if (fZ > 0) return (10e10);
463     else return (-10e10);
464     }
465     void RotateX(Double_t angle) {
466     /// Rotates around the x-axis.
467     Double_t s = TMath::Sin(angle);
468     Double_t c = TMath::Cos(angle);
469     Double_t yy = fY;
470     fY = c*yy - s*fZ;
471     fZ = s*yy + c*fZ;
472     }
473    
474     void RotateY(Double_t angle) {
475     /// Rotates around the y-axis.
476     Double_t s = TMath::Sin(angle);
477     Double_t c = TMath::Cos(angle);
478     Double_t zz = fZ;
479     fZ = c*zz - s*fX;
480     fX = s*zz + c*fX;
481     }
482    
483     void RotateZ(Double_t angle) {
484     /// Rotates around the z-axis.
485     Double_t s = TMath::Sin(angle);
486     Double_t c = TMath::Cos(angle);
487     Double_t xx = fX;
488     fX = c*xx - s*fY;
489     fY = s*xx + c*fY;
490     }
491    
492     void RotateUz(const TMBVector3& NewUzVector) {
493     /// Rotates reference frame from Uz to newUz (must be unit vector!)
494     Double_t u1 = NewUzVector.fX;
495     Double_t u2 = NewUzVector.fY;
496     Double_t u3 = NewUzVector.fZ;
497     Double_t up = u1*u1 + u2*u2;
498    
499     if (up>0.) {
500     up = TMath::Sqrt(up);
501     Double_t px = fX, py = fY, pz = fZ;
502     fX = (u1*u3*px - u2*py + u1*up*pz)/up;
503     fY = (u2*u3*px + u1*py + u2*up*pz)/up;
504     fZ = (u3*u3*px - px + u3*up*pz)/up;
505     }
506     else if (u3 < 0.) { fX = -fX; fZ = -fZ; } // phi=0 teta=pi
507     else {};
508     }
509    
510     void Rotate(Double_t angle, const TMBVector3 &axis) {
511     /// Rotates around the axis specified by another vector
512     TRotation trans;
513     trans.Rotate(angle, (TVector3)axis);
514     operator*=(trans);
515     }
516    
517     TMBVector3 & operator *= (const TRotation &m) {
518     /// Transform with a rotation matrix
519     return *this = m * (*this);
520     }
521     TMBVector3 & Transform(const TRotation &m) {
522     /// Transform with a rotation matrix
523     return *this = m * (*this);
524     }
525    
526     TVector2 XYvector() const {
527     /// TVector2 containing x and y components
528     return TVector2(fX,fY); }
529    
530     operator TVector3() const {
531     /// cast to a TVector3
532     return TVector3(X(),Y(),Z()); }
533    
534     void Print(Option_t* option="") const {
535     /// print components to stdout
536     Printf("%s %s (x,y,z)=(%f,%f,%f) (rho,theta,phi)=(%f,%f,%f)",
537     GetName(),GetTitle(),X(),Y(),Z(),
538     Mag3(),Theta()*TMath::RadToDeg(),Phi()*TMath::RadToDeg());
539     }
540    
541     // Helper to test if two FP numbers are equivalent within machine precision.
542     static bool is_equal (double x1, double x2);
543    
544     private:
545     Double32_t fX; ///< X component (left-right)
546     Double32_t fY; ///< Y component (up-down)
547     Double32_t fZ; ///< Z component (along the beam)
548    
549     //ClassDef(TMBVector3,1) // A 3D physics vector
550    
551     };
552    
553     inline
554     TMBVector3 operator + (const TMBVector3 &a, const TMBVector3 &b) {
555     /// Addition of 3-vectors.
556     return TVector3(a.X() + b.X(), a.Y() + b.Y(), a.Z() + b.Z()); }
557    
558     inline
559     TMBVector3 operator - (const TMBVector3 &a, const TMBVector3 &b) {
560     /// Subtraction of 3-vectors.
561     return TVector3(a.X() - b.X(), a.Y() - b.Y(), a.Z() - b.Z()); }
562    
563     inline
564     Double_t operator * (const TMBVector3 &a, const TMBVector3 &b) {
565     /// Dot product of two vectors
566     return a.Dot(b); }
567    
568     inline
569     TMBVector3 operator * (const TMBVector3 &p, Double_t a) {
570     /// Scalar product of 3-vectors.
571     return TVector3(a*p.X(), a*p.Y(), a*p.Z()); }
572    
573     inline
574     TMBVector3 operator * (Double_t a, const TMBVector3 &p) {
575     /// Scaling of 3-vectors with a real number
576     return TVector3(a*p.X(), a*p.Y(), a*p.Z()); }
577    
578     inline
579     TMBVector3 operator * (const TMatrix &m, const TMBVector3 &v) {
580     /// Transform with matrix
581     return TVector3( m(0,0)*v.X()+m(0,1)*v.Y()+m(0,2)*v.Z(),
582     m(1,0)*v.X()+m(1,1)*v.Y()+m(1,2)*v.Z(),
583     m(2,0)*v.X()+m(2,1)*v.Y()+m(2,2)*v.Z());
584     }
585    
586     /*************************************************************************
587     * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
588     * All rights reserved. *
589     * *
590     * For the licensing terms see $ROOTSYS/LICENSE. *
591     * For the list of contributors see $ROOTSYS/README/CREDITS. *
592     *************************************************************************/
593    
594     // Author: Pasha Murat, Peter Malzacher 12/02/99
595    
596     #endif // INCLUDE_TMBVECTOR3