// -*- C++ -*- // // This file is a side header, dependant on CLHEP. // // It declares, defines, and implements the UnitVector class present in ZOOM // PhysicsVectors. It does so with no non-inline implementation code; thus // no code goes into the CLHEP library, and if this header is not included, // the existence of UnitVector is quite invisible. // // Most methods merely call the corresponding Hep3Vector method. // The mechanism for doing this in non-trivial cases is a C-style cast // WHICH DEPENDS CRITICALLY ON THE FACT THAT THE REPRESENTATIONS OF // Hep#Vector and UnitVector MATCH! // // IF THE PRIVATE DATA OF Hep3Vector CHANGES, THE PRIVATE DATA HERE MUST! // // One could use the safer operator Hep3Vector, as in // Hepdouble getTheta const {return (this->operator Hep3Vector()).gettheta();} // but this implies creation of a temporary and in some cases that would risk // a significant performance hit. (Optimization can trivially eliminate that // hit but can we trust optimizers these days?) // // .SS Authors // Mark Fischler // #ifndef UNITVECTOR_H #define UNITVECTOR_H #ifdef GNUPRAGMA #pragma interface #endif #include "CLHEP/config/CLHEP.h" #include "PhysicsVectors/SpaceVector.h" // NOTE: UnitVector will be typedefed to HepUnit3Vector inside the // optional zmpv namespace. Thus if and when HepUnit3Vector is // accepted into CLHEP, the relationship will be analogous to that // between SpaceVector and Hep3Vector. class HepUnit3Vector { protected: // The IDENTICAL variables as Hep3Vector, in the same order HepDouble dx; HepDouble dy; HepDouble dz; public: // **** Conversion to and construction from Hep3Vector **** operator SpaceVector() const {return SpaceVector( dx, dy, dz );} operator Hep3Vector() const {return Hep3Vector( dx, dy, dz );} // Thus when used as a const ARGUMENT, // a HepUnit3Vector may replace a SpaceVector // ****Constructors and setting entire vector **** HepUnit3Vector() : dx(0.0), dy(0.0), dz(1.0) {} void set (HepDouble x, HepDouble y, HepDouble z) {((Hep3Vector*)this)->set(x, y, z); ((Hep3Vector*)this)->setR(1.0);} HepUnit3Vector (HepDouble x, HepDouble y, HepDouble z) : dx(x), dy(y), dz(z) {((Hep3Vector*)this)->setR(1.0);} // Normalize these cartesian coordinates. void set (const Hep3Vector & v) {((Hep3Vector*)this)->set(v.x(), v.y(), v.z()); ((Hep3Vector*)this)->setR(1.0);} HepUnit3Vector (const Hep3Vector & v) : dx(v.x()), dy(v.y()), dz(v.z()) {((Hep3Vector*)this)->setR(1.0);} // Normalize the cartesian coordinates defined by this vector. HepUnit3Vector & rectify() {HepDouble radius= sqrt( dx*dx+dy*dy+dz*dz); dx=dx/radius; dy=dy/radius; dz=dz/radius; return *this;} // No cylindrical coordinates HepUnit3Vector (const HepUnit3Vector &u) : dx(u.dx), dy(u.dy), dz(u.dz) {} // The copy constructor. ~HepUnit3Vector() {} // The destructor. Not virtual - inheritance from this class is dangerous. // **** Component Access **** HepDouble operator () (int i) const {return ((Hep3Vector*)this)->operator()(i);} HepDouble operator [] (int i) const {return ((Hep3Vector*)this)->operator[](i);} // Get components by index // No Setting components by index. HepDouble getX() const {return dx;} HepDouble getY() const {return dy;} HepDouble getZ() const {return dz;} // The components in cartesian coordinate system. HepDouble x() const {return dx;} HepDouble y() const {return dy;} HepDouble z() const {return dz;} // The components in cartesian coordinate system. Same as getX() etc. // No Setting the components in cartesian coordinate system. // No Setting all three components in cartesian coordinate system. HepDouble phi() const {return ((Hep3Vector*)this)->phi();} HepDouble getPhi() const {return phi();} // The azimuth angle. void setPhi(HepDouble x) { ((Hep3Vector*)this)->setPhi(x);} // Set phi keeping theta constant HepDouble theta() const {return ((Hep3Vector*)this)->theta();} HepDouble getTheta() const {return theta();} HepDouble angle() const {return theta();} // The polar angle. void setTheta(HepDouble x) { ((Hep3Vector*)this)->setTheta(x);} // Set theta keeping phi constant HepDouble cosTheta() const {return dz;} // Cosine of the polar angle. HepDouble cos2Theta() const {return dz*dz;} // Cosine squared of the polar angle. HepDouble mag2() const {return 1.0;} // The magnitude squared (r^2 in spherical coordinate system). HepDouble mag() const {return 1.0;} HepDouble getR() const {return 1.0;} HepDouble r() const {return 1.0;} // The magnitude (r in spherical coordinate system). // No setMag() or setR() inline void setR ( HepDouble s ); // setMag() HepDouble perp2() const { return dx*dx + dy*dy; } // The transverse component squared (rho^2 in cylindrical coordinate system). HepDouble perp() const { return sqrt(perp2()); } inline HepDouble rho () const {return perp();} inline HepDouble getRho () const {return perp();} // The transverse component (rho in cylindrical coordinate system). // No setPerp or setRho // No setCylTheta // Set theta while keeping transvers component and phi fixed HepDouble perp2(const Hep3Vector & v) const {return ((Hep3Vector*)this)->perp2(v);} // The transverse component w.r.t. given axis squared. HepDouble perp2(const HepUnit3Vector & u) const { HepDouble uv = dot(u); HepDouble p2 = 1.0 - uv*uv; return p2>0 ? p2:0; } HepDouble perp(const Hep3Vector & v) const {return sqrt(perp2(v));} // The transverse component w.r.t. given axis. HepDouble perp(const HepUnit3Vector & u) const {return sqrt(perp2(u));} // **** Assignment **** HepUnit3Vector & operator = (const HepUnit3Vector & u) {dx=u.dx; dy=u.dy; dz=u.dz; return *this;} // NO operator += // NO operator -= // NO operator *= // NO operator /= HepUnit3Vector operator - () const {return HepUnit3Vector(-dx, -dy, -dz);} // Unary minus. // **** Comparisions **** HepInt compare (const Hep3Vector & v) const {return ((Hep3Vector*)this)->compare(v);} HepBoolean operator == (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator==(v);} HepBoolean operator != (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator!=(v);} HepBoolean operator > (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator>(v);} HepBoolean operator < (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator<(v);} HepBoolean operator>= (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator>=(v);} HepBoolean operator<= (const Hep3Vector & v) const {return ((Hep3Vector*)this)->operator<=(v);} // dictionary ordering according to z, then y, then x component HepBoolean isNear (const Hep3Vector & v, HepDouble epsilon=Hep3Vector::getTolerance()) const {return ((Hep3Vector*)this)->isNear(v,epsilon);} HepBoolean isNear (const HepUnit3Vector & u, HepDouble epsilon=Hep3Vector::getTolerance()) const { return (*this-u).mag2() <= epsilon*epsilon; } HepDouble howNear(const Hep3Vector & v ) const {return (*this - v).mag();} HepDouble deltaR(const Hep3Vector & v) const {return ((Hep3Vector*)this)->deltaR(v);} inline HepDouble diff2 (const Hep3Vector & v) const {return ((Hep3Vector*)this)->diff2(v);} // |v1-v2|**2 HepBoolean isParallel (const Hep3Vector & v, HepDouble epsilon=Hep3Vector::getTolerance()) const {return ((Hep3Vector*)this)->isParallel(v,epsilon);} // Are the vectors parallel, within the given tolerance? HepBoolean isOrthogonal (const Hep3Vector & v, HepDouble epsilon=Hep3Vector::getTolerance()) const {return ((Hep3Vector*)this)->isOrthogonal(v,epsilon);} // Are the vectors orthogonal, within the given tolerance? HepDouble howParallel (const Hep3Vector & v) const {return ((Hep3Vector*)this)->howParallel(v);} // | v1.cross(v2) / v1.dot(v2) |, to a maximum of 1. HepDouble howOrthogonal (const Hep3Vector & v) const {return ((Hep3Vector*)this)->howOrthogonal(v);} // | v1.dot(v2) / v1.cross(v2) |, to a maximum of 1. // No setTolerance or getTolerance; uses the Hep3Vector tolerance // **** Intrinsic properties **** Hep3Vector unit() const {return (Hep3Vector)(*this);} // No orthogonal() // No beta() // No gamma() // No coLinearRapidity() // No rapidity() HepDouble pseudoRapidity() const {return ((Hep3Vector*)this)->pseudoRapidity();} HepDouble eta () const {return pseudoRapidity();} HepDouble getEta () const {return pseudoRapidity();} void setEta ( HepDouble p ) {((Hep3Vector*)this)->setEta(p);} // NO setCylEta // **** Combining with other vectors **** HepDouble dot(const Hep3Vector & v) const {return ((Hep3Vector*)this)->dot(v);} Hep3Vector cross(const Hep3Vector & v) const {return ((Hep3Vector*)this)->cross(v);} HepDouble angle(const Hep3Vector & v) const {return ((Hep3Vector*)this)->angle(v);} HepDouble theta(const Hep3Vector & v) const {return angle(v);} HepDouble cosTheta (const HepUnit3Vector & u) const {return dot(u);} HepDouble cosTheta (const Hep3Vector & v) const {return ((Hep3Vector*)this)->cosTheta(v);} HepDouble cos2Theta(const HepUnit3Vector & u) const {HepDouble c = dot(u); return c*c;} HepDouble cos2Theta(const Hep3Vector & v) const {return ((Hep3Vector*)this)->cos2Theta(v);} // cos^2 of the angle between two vectors Hep3Vector project () const {return Hep3Vector(0,0,dz);} Hep3Vector project (const HepUnit3Vector & u) const {return dot(u)*u;} Hep3Vector project (const Hep3Vector & v) const {return ((Hep3Vector*)this)->project(v);} // projection of a vector along a direction. Hep3Vector perpPart() const {return Hep3Vector(dx,dy,0);} Hep3Vector perpPart (const HepUnit3Vector & u) const {return (*this)-dot(u)*u;} Hep3Vector perpPart (const Hep3Vector & v) const {return ((Hep3Vector*)this)->perpPart(v);} // vector minus its projection along a direction. // no rapidity (v) HepDouble eta(const Hep3Vector & v) const {return ((Hep3Vector*)this)->eta(v);} // - ln tan of the angle beween the vector and the ref direction. // **** Angle decomposition **** // Note: All of these could be done faster, especially using a UnitVector // as the reference. However, these are not extensively used and // thus we use the simplest possible coding, based on Hep3Vector. HepDouble polarAngle (const Hep3Vector & v2) const {return ((Hep3Vector*)this)->polarAngle(v2);} // The reference direction is Z: the polarAngle is abs(u.theta()-v2.theta()). HepDouble azimAngle (const Hep3Vector & v2) const {return ((Hep3Vector*)this)->azimAngle(v2);} // The reference direction is Z: the azimAngle is u.phi()-v2.phi() HepDouble polarAngle (const Hep3Vector & v2, const Hep3Vector & ref) const {return ((Hep3Vector*)this)->polarAngle(v2,ref);} // For arbitrary reference direction, // polarAngle is abs(v.angle(ref) - v2.angle(ref)). HepDouble azimAngle (const Hep3Vector & v2, const Hep3Vector & ref) const {return ((Hep3Vector*)this)->azimAngle(v2,ref);} // To compute azimangle, project u and v2 into the plane normal to // the reference direction. Then in that plane take the angle going // clockwise around the direction from projection of u to that of v2. // **** Rotating **** Hep3Vector & rotateX(HepDouble delta) {return ((Hep3Vector*)this)->rotateX(delta);} Hep3Vector & rotateY(HepDouble delta) {return ((Hep3Vector*)this)->rotateY(delta);} Hep3Vector & rotateZ(HepDouble delta) {return ((Hep3Vector*)this)->rotateZ(delta);} // No rotateUz(const Hep3Vector&); Hep3Vector & rotate (const Hep3Vector & axis, HepDouble delta) {return ((Hep3Vector*)this)->rotate(axis,delta);} Hep3Vector & rotate (HepDouble delta, const Hep3Vector & v) {return rotate(v,delta);} // no operator *= (const HepRotation &); // no transform(const HepRotation &); Hep3Vector & rotate (const HepAxisAngle & ax) {return ((Hep3Vector*)this)->rotate(ax);} Hep3Vector & rotate (const HepEulerAngles & e) {return ((Hep3Vector*)this)->rotate(e);} Hep3Vector & rotate (HepDouble phi, HepDouble theta, HepDouble psi) {return ((Hep3Vector*)this)->rotate(phi,theta,psi);} // Rotate via Euler Angles. Our Euler Angles conventions are // those of Goldstein Classical Mechanics page 107. // **** Global methods friend declatations **** inline friend HepUnit3Vector rotationXOf (const HepUnit3Vector & u, HepDouble delta); inline friend HepUnit3Vector rotationYOf (const HepUnit3Vector & u, HepDouble delta); inline friend HepUnit3Vector rotationZOf (const HepUnit3Vector & u, HepDouble delta); inline friend HepUnit3Vector rotationOf (const HepUnit3Vector & u, const Hep3Vector & axis, HepDouble delta); inline friend HepUnit3Vector rotationOf (const HepUnit3Vector & u, const HepAxisAngle & ax); inline friend HepUnit3Vector rotationOf (const HepUnit3Vector & u, HepDouble phi, HepDouble theta, HepDouble psi); inline friend HepUnit3Vector rotationOf (const HepUnit3Vector & u, const HepEulerAngles & e); }; // **** Global Methods **** HepUnit3Vector rotationXOf (const HepUnit3Vector & u, HepDouble delta) { Hep3Vector v( rotationXOf((Hep3Vector)u,delta) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationYOf (const HepUnit3Vector & u, HepDouble delta) { Hep3Vector v( rotationYOf((Hep3Vector)u,delta) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationZOf (const HepUnit3Vector & u, HepDouble delta) { Hep3Vector v( rotationZOf((Hep3Vector)u,delta) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationOf (const HepUnit3Vector & u, const Hep3Vector & axis, HepDouble delta) { Hep3Vector v( rotationOf((Hep3Vector)u,axis,delta) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationOf (const HepUnit3Vector & u, const HepAxisAngle & ax) { Hep3Vector v( rotationOf((Hep3Vector)u,ax) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationOf (const HepUnit3Vector & u, HepDouble phi, HepDouble theta, HepDouble psi) { Hep3Vector v( rotationOf((Hep3Vector)u,phi,theta,psi) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} HepUnit3Vector rotationOf (const HepUnit3Vector & u, const HepEulerAngles & e) { Hep3Vector v( rotationOf((Hep3Vector)u,e) ); HepUnit3Vector w; w.dx = v.x(); w.dy = v.y(); w.dz=v.z(); return w;} // operator << (HepStd::ostream & os, const Hep3Vector &u) // not needed since there is a conversion to Hep3Vector inline HepStd::istream & operator >> (HepStd::istream &is, HepUnit3Vector &u) { Hep3Vector v; is >> v; u.set (v.x(), v.y(), v.z()); return is; } // Input from a stream, normalizing the three numbers. ZM_BEGIN_NAMESPACE( zmpv ) /* namespace zmpv { */ typedef double Scalar; class UnitVector : public HepUnit3Vector { public: // Constructors parallel to those for HepUnit3Vector UnitVector() { dx = 0.0; dy = 0.0; dz = 1.0; } UnitVector (HepDouble x, HepDouble y, HepDouble z) {((Hep3Vector*)this)->set(x,y,z); ((Hep3Vector*)this)->setR(1.0);} void set (HepDouble x, HepDouble y, HepDouble z) {((Hep3Vector*)this)->set(x, y, z); ((Hep3Vector*)this)->setR(1.0);} // Normalize these cartesian coordinates. UnitVector (const Hep3Vector & v) {((Hep3Vector*)this)->operator=(v); ((Hep3Vector*)this)->setR(1.0);} // Normalize the cartesian coordinates defined by this vector. UnitVector (const HepUnit3Vector &u) : HepUnit3Vector(u) {} UnitVector (const UnitVector &u) : HepUnit3Vector(u) {} // Copy constructors. ~UnitVector() {} // The destructor. Not virtual - inheritance from this class is dangerous. // Spherical coordinate constructors: void set (HepDouble theta, ZMpvRADIANS_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} void set (HepDouble theta, ZMpvRADIANS_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} void set (HepDouble theta, ZMpvDEGREES_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} void set (HepDouble theta, ZMpvDEGREES_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} void set (HepDouble theta, ZMpvETA_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} void set (HepDouble theta, ZMpvETA_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {((SpaceVector*)this)->set(1.0, theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvRADIANS_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvRADIANS_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvDEGREES_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvDEGREES_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvETA_t thetaUnits, HepDouble phi, ZMpvRADIANS_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} UnitVector (HepDouble theta, ZMpvETA_t thetaUnits, HepDouble phi, ZMpvDEGREES_t phiUnits) {set(theta, thetaUnits, phi, phiUnits);} }; // UnitVector // **** Axis UnitVectors **** static const UnitVector X_HAT (1,0,0); static const UnitVector Y_HAT (0,1,0); static const UnitVector Z_HAT (0,0,1); ZM_END_NAMESPACE( zmpv ) /* } // namespace zmpv */ #endif /* UNITVECTOR_H */