source: trunk/CLHEP/src/ThreeVector.cc@ 20

Last change on this file since 20 was 4, checked in by Pavel Demin, 16 years ago

first commit

File size: 8.8 KB
RevLine 
[4]1// -*- C++ -*-
2// $Id: ThreeVector.cc,v 1.1 2008-06-04 14:15:11 demin Exp $
3// ---------------------------------------------------------------------------
4//
5// This file is a part of the CLHEP - a Class Library for High Energy Physics.
6//
7// This is the implementation of the Hep3Vector class.
8//
9// See also ThreeVectorR.cc for implementation of Hep3Vector methods which
10// would couple in all the HepRotation methods.
11//
12
13#ifdef GNUPRAGMA
14#pragma implementation
15#endif
16
17#include "CLHEP/Vector/defs.h"
18#include "CLHEP/Vector/ThreeVector.h"
19#include "CLHEP/Vector/ZMxpv.h"
20#include "CLHEP/Units/PhysicalConstants.h"
21
22#include <cmath>
23#include <iostream>
24
25namespace CLHEP {
26
27void Hep3Vector::setMag(double ma) {
28 double factor = mag();
29 if (factor == 0) {
30 ZMthrowA ( ZMxpvZeroVector (
31 "Hep3Vector::setMag : zero vector can't be stretched"));
32 }else{
33 factor = ma/factor;
34 setX(x()*factor);
35 setY(y()*factor);
36 setZ(z()*factor);
37 }
38}
39
40double Hep3Vector::operator () (int i) const {
41 switch(i) {
42 case X:
43 return x();
44 case Y:
45 return y();
46 case Z:
47 return z();
48 default:
49 std::cerr << "Hep3Vector subscripting: bad index (" << i << ")"
50 << std::endl;
51 }
52 return 0.;
53}
54
55double & Hep3Vector::operator () (int i) {
56 static double dummy;
57 switch(i) {
58 case X:
59 return dx;
60 case Y:
61 return dy;
62 case Z:
63 return dz;
64 default:
65 std::cerr
66 << "Hep3Vector subscripting: bad index (" << i << ")"
67 << std::endl;
68 return dummy;
69 }
70}
71
72Hep3Vector & Hep3Vector::rotateUz(const Hep3Vector& NewUzVector) {
73 // NewUzVector must be normalized !
74
75 double u1 = NewUzVector.x();
76 double u2 = NewUzVector.y();
77 double u3 = NewUzVector.z();
78 double up = u1*u1 + u2*u2;
79
80 if (up>0) {
81 up = sqrt(up);
82 double px = dx, py = dy, pz = dz;
83 dx = (u1*u3*px - u2*py)/up + u1*pz;
84 dy = (u2*u3*px + u1*py)/up + u2*pz;
85 dz = -up*px + u3*pz;
86 }
87 else if (u3 < 0.) { dx = -dx; dz = -dz; } // phi=0 teta=pi
88 else {};
89 return *this;
90}
91
92double Hep3Vector::pseudoRapidity() const {
93 double m = mag();
94 if ( m== 0 ) return 0.0;
95 if ( m== z() ) return 1.0E72;
96 if ( m== -z() ) return -1.0E72;
97 return 0.5*log( (m+z())/(m-z()) );
98}
99
100std::ostream & operator<< (std::ostream & os, const Hep3Vector & v) {
101 return os << "(" << v.x() << "," << v.y() << "," << v.z() << ")";
102}
103
104void ZMinput3doubles ( std::istream & is, const char * type,
105 double & x, double & y, double & z );
106
107std::istream & operator>>(std::istream & is, Hep3Vector & v) {
108 double x, y, z;
109 ZMinput3doubles ( is, "Hep3Vector", x, y, z );
110 v.set(x, y, z);
111 return is;
112} // operator>>()
113
114const Hep3Vector HepXHat(1.0, 0.0, 0.0);
115const Hep3Vector HepYHat(0.0, 1.0, 0.0);
116const Hep3Vector HepZHat(0.0, 0.0, 1.0);
117
118//-------------------
119//
120// New methods introduced when ZOOM PhysicsVectors was merged in:
121//
122//-------------------
123
124Hep3Vector & Hep3Vector::rotateX (double phi) {
125 double sinphi = sin(phi);
126 double cosphi = cos(phi);
127 double ty;
128 ty = dy * cosphi - dz * sinphi;
129 dz = dz * cosphi + dy * sinphi;
130 dy = ty;
131 return *this;
132} /* rotateX */
133
134Hep3Vector & Hep3Vector::rotateY (double phi) {
135 double sinphi = sin(phi);
136 double cosphi = cos(phi);
137 double tz;
138 tz = dz * cosphi - dx * sinphi;
139 dx = dx * cosphi + dz * sinphi;
140 dz = tz;
141 return *this;
142} /* rotateY */
143
144Hep3Vector & Hep3Vector::rotateZ (double phi) {
145 double sinphi = sin(phi);
146 double cosphi = cos(phi);
147 double tx;
148 tx = dx * cosphi - dy * sinphi;
149 dy = dy * cosphi + dx * sinphi;
150 dx = tx;
151 return *this;
152} /* rotateZ */
153
154bool Hep3Vector::isNear(const Hep3Vector & v, double epsilon) const {
155 double limit = dot(v)*epsilon*epsilon;
156 return ( (*this - v).mag2() <= limit );
157} /* isNear() */
158
159double Hep3Vector::howNear(const Hep3Vector & v ) const {
160 // | V1 - V2 | **2 / V1 dot V2, up to 1
161 double d = (*this - v).mag2();
162 double vdv = dot(v);
163 if ( (vdv > 0) && (d < vdv) ) {
164 return sqrt (d/vdv);
165 } else if ( (vdv == 0) && (d == 0) ) {
166 return 0;
167 } else {
168 return 1;
169 }
170} /* howNear */
171
172double Hep3Vector::deltaPhi (const Hep3Vector & v2) const {
173 double dphi = v2.getPhi() - getPhi();
174 if ( dphi > CLHEP::pi ) {
175 dphi -= CLHEP::twopi;
176 } else if ( dphi <= -CLHEP::pi ) {
177 dphi += CLHEP::twopi;
178 }
179 return dphi;
180} /* deltaPhi */
181
182double Hep3Vector::deltaR ( const Hep3Vector & v ) const {
183 double a = eta() - v.eta();
184 double b = deltaPhi(v);
185 return sqrt ( a*a + b*b );
186} /* deltaR */
187
188double Hep3Vector::cosTheta(const Hep3Vector & q) const {
189 double arg;
190 double ptot2 = mag2()*q.mag2();
191 if(ptot2 <= 0) {
192 arg = 0.0;
193 }else{
194 arg = dot(q)/sqrt(ptot2);
195 if(arg > 1.0) arg = 1.0;
196 if(arg < -1.0) arg = -1.0;
197 }
198 return arg;
199}
200
201double Hep3Vector::cos2Theta(const Hep3Vector & q) const {
202 double arg;
203 double ptot2 = mag2();
204 double qtot2 = q.mag2();
205 if ( ptot2 == 0 || qtot2 == 0 ) {
206 arg = 1.0;
207 }else{
208 double pdq = dot(q);
209 arg = (pdq/ptot2) * (pdq/qtot2);
210 // More naive methods overflow on vectors which can be squared
211 // but can't be raised to the 4th power.
212 if(arg > 1.0) arg = 1.0;
213 }
214 return arg;
215}
216
217void Hep3Vector::setEta (double eta) {
218 double phi = 0;
219 double r;
220 if ( (dx == 0) && (dy == 0) ) {
221 if (dz == 0) {
222 ZMthrowC (ZMxpvZeroVector(
223 "Attempt to set eta of zero vector -- vector is unchanged"));
224 return;
225 }
226 ZMthrowC (ZMxpvZeroVector(
227 "Attempt to set eta of vector along Z axis -- will use phi = 0"));
228 r = fabs(dz);
229 } else {
230 r = getR();
231 phi = getPhi();
232 }
233 double tanHalfTheta = exp ( -eta );
234 double cosTheta =
235 (1 - tanHalfTheta*tanHalfTheta) / (1 + tanHalfTheta*tanHalfTheta);
236 dz = r * cosTheta;
237 double rho = r*sqrt(1 - cosTheta*cosTheta);
238 dy = rho * sin (phi);
239 dx = rho * cos (phi);
240 return;
241}
242
243void Hep3Vector::setCylTheta (double theta) {
244
245 // In cylindrical coords, set theta while keeping rho and phi fixed
246
247 if ( (dx == 0) && (dy == 0) ) {
248 if (dz == 0) {
249 ZMthrowC (ZMxpvZeroVector(
250 "Attempt to set cylTheta of zero vector -- vector is unchanged"));
251 return;
252 }
253 if (theta == 0) {
254 dz = fabs(dz);
255 return;
256 }
257 if (theta == CLHEP::pi) {
258 dz = -fabs(dz);
259 return;
260 }
261 ZMthrowC (ZMxpvZeroVector(
262 "Attempt set cylindrical theta of vector along Z axis "
263 "to a non-trivial value, while keeping rho fixed -- "
264 "will return zero vector"));
265 dz = 0;
266 return;
267 }
268 if ( (theta < 0) || (theta > CLHEP::pi) ) {
269 ZMthrowC (ZMxpvUnusualTheta(
270 "Setting Cyl theta of a vector based on a value not in [0, PI]"));
271 // No special return needed if warning is ignored.
272 }
273 double phi (getPhi());
274 double rho = getRho();
275 if ( (theta == 0) || (theta == CLHEP::pi) ) {
276 ZMthrowC (ZMxpvInfiniteVector(
277 "Attempt to set cylindrical theta to 0 or PI "
278 "while keeping rho fixed -- infinite Z will be computed"));
279 dz = (theta==0) ? 1.0E72 : -1.0E72;
280 return;
281 }
282 dz = rho / tan (theta);
283 dy = rho * sin (phi);
284 dx = rho * cos (phi);
285
286} /* setCylTheta */
287
288void Hep3Vector::setCylEta (double eta) {
289
290 // In cylindrical coords, set eta while keeping rho and phi fixed
291
292 double theta = 2 * atan ( exp (-eta) );
293
294 //-| The remaining code is similar to setCylTheta, The reason for
295 //-| using a copy is so as to be able to change the messages in the
296 //-| ZMthrows to say eta rather than theta. Besides, we assumedly
297 //-| need not check for theta of 0 or PI.
298
299 if ( (dx == 0) && (dy == 0) ) {
300 if (dz == 0) {
301 ZMthrowC (ZMxpvZeroVector(
302 "Attempt to set cylEta of zero vector -- vector is unchanged"));
303 return;
304 }
305 if (theta == 0) {
306 dz = fabs(dz);
307 return;
308 }
309 if (theta == CLHEP::pi) {
310 dz = -fabs(dz);
311 return;
312 }
313 ZMthrowC (ZMxpvZeroVector(
314 "Attempt set cylindrical eta of vector along Z axis "
315 "to a non-trivial value, while keeping rho fixed -- "
316 "will return zero vector"));
317 dz = 0;
318 return;
319 }
320 double phi (getPhi());
321 double rho = getRho();
322 dz = rho / tan (theta);
323 dy = rho * sin (phi);
324 dx = rho * cos (phi);
325
326} /* setCylEta */
327
328
329Hep3Vector operator/ ( const Hep3Vector & v1, double c ) {
330 if (c == 0) {
331 ZMthrowA ( ZMxpvInfiniteVector (
332 "Attempt to divide vector by 0 -- "
333 "will produce infinities and/or NANs"));
334 }
335 double oneOverC = 1.0/c;
336 return Hep3Vector ( v1.x() * oneOverC,
337 v1.y() * oneOverC,
338 v1.z() * oneOverC );
339} /* v / c */
340
341Hep3Vector & Hep3Vector::operator/= (double c) {
342 if (c == 0) {
343 ZMthrowA (ZMxpvInfiniteVector(
344 "Attempt to do vector /= 0 -- "
345 "division by zero would produce infinite or NAN components"));
346 }
347 double oneOverC = 1.0/c;
348 dx *= oneOverC;
349 dy *= oneOverC;
350 dz *= oneOverC;
351 return *this;
352}
353
354double Hep3Vector::tolerance = Hep3Vector::ToleranceTicks * 2.22045e-16;
355
356} // namespace CLHEP
357
358
359
Note: See TracBrowser for help on using the repository browser.