rivet is hosted by Hepforge, IPPP Durham
Vector3.hh
Go to the documentation of this file.
00001 #ifndef RIVET_MATH_VECTOR3
00002 #define RIVET_MATH_VECTOR3
00003 
00004 #include "Rivet/Math/MathHeader.hh"
00005 #include "Rivet/Math/MathUtils.hh"
00006 #include "Rivet/Math/VectorN.hh"
00007 
00008 namespace Rivet {
00009 
00010 
00011   class Vector3;
00012   typedef Vector3 ThreeVector;
00013   class Matrix3;
00014 
00015   Vector3 multiply(const double, const Vector3&);
00016   Vector3 multiply(const Vector3&, const double);
00017   Vector3 add(const Vector3&, const Vector3&);
00018   Vector3 operator*(const double, const Vector3&);
00019   Vector3 operator*(const Vector3&, const double);
00020   Vector3 operator/(const Vector3&, const double);
00021   Vector3 operator+(const Vector3&, const Vector3&);
00022   Vector3 operator-(const Vector3&, const Vector3&);
00023 
00024 
00025   /// @brief Three-dimensional specialisation of Vector.
00026   class Vector3 : public Vector<3> {
00027 
00028     friend class Matrix3;
00029     friend Vector3 multiply(const double, const Vector3&);
00030     friend Vector3 multiply(const Vector3&, const double);
00031     friend Vector3 add(const Vector3&, const Vector3&);
00032     friend Vector3 subtract(const Vector3&, const Vector3&);
00033 
00034   public:
00035     Vector3() : Vector<3>() { }
00036 
00037     template<typename V3>
00038     Vector3(const V3& other) {
00039       this->setX(other.x());
00040       this->setY(other.y());
00041       this->setZ(other.z());
00042     }
00043 
00044     Vector3(const Vector<3>& other) {
00045       this->setX(other.get(0));
00046       this->setY(other.get(1));
00047       this->setZ(other.get(2));
00048     }
00049 
00050     Vector3(double x, double y, double z) {
00051       this->setX(x);
00052       this->setY(y);
00053       this->setZ(z);
00054     }
00055 
00056     ~Vector3() { }
00057 
00058   public:
00059     static Vector3 mkX() { return Vector3(1,0,0); }
00060     static Vector3 mkY() { return Vector3(0,1,0); }
00061     static Vector3 mkZ() { return Vector3(0,0,1); }
00062 
00063   public:
00064     double x() const { return get(0); }
00065     double y() const { return get(1); }
00066     double z() const { return get(2); }
00067     Vector3& setX(double x) { set(0, x); return *this; }
00068     Vector3& setY(double y) { set(1, y); return *this; }
00069     Vector3& setZ(double z) { set(2, z); return *this; }
00070 
00071     double dot(const Vector3& v) const {
00072       return _vec.dot(v._vec);
00073     }
00074 
00075     Vector3 cross(const Vector3& v) const {
00076       Vector3 result;
00077       result._vec = _vec.cross(v._vec);
00078       return result;
00079     }
00080 
00081     double angle(const Vector3& v) const {
00082       const double localDotOther = unit().dot(v.unit());
00083       if (fuzzyEquals(localDotOther, 1.0)) return 0.0;
00084       else if (fuzzyEquals(localDotOther, -1.0)) return M_PI;
00085       return acos(localDotOther);
00086     }
00087 
00088     Vector3 unit() const {
00089       /// @todo What to do in this situation?
00090       if (isZero()) return *this;
00091       else return *this * 1.0/this->mod();
00092     }
00093 
00094     double polarRadius2() const {
00095       return x()*x() + y()*y();
00096     }
00097 
00098     /// Synonym for polarRadius2
00099     double perp2() const {
00100       return polarRadius2();
00101     }
00102 
00103     /// Synonym for polarRadius2
00104     double rho2() const {
00105       return polarRadius2();
00106     }
00107 
00108     double polarRadius() const {
00109       return sqrt(polarRadius2());
00110     }
00111 
00112     /// Synonym for polarRadius
00113     double perp() const {
00114       return polarRadius();
00115     }
00116 
00117     /// Synonym for polarRadius
00118     double rho() const {
00119       return polarRadius();
00120     }
00121 
00122     /// Angle subtended by the vector's projection in x-y and the x-axis.
00123     double azimuthalAngle(const PhiMapping mapping = ZERO_2PI) const {
00124       // If this is a null vector, return zero rather than let atan2 set an error state
00125       if (Rivet::isZero(mod2())) return 0.0;
00126 
00127       // Calculate the arctan and correct for numerical boundary cases
00128       double value = atan2( y(), x() );
00129       if (value > 2*PI || value < -2*PI){
00130         value = fmod(value, 2*PI);
00131       }
00132       if (value <= -PI) value += 2*PI;
00133       if (value >   PI) value -= 2*PI;
00134 
00135       // Return in the requested range
00136       switch (mapping) {
00137       case MINUSPI_PLUSPI:
00138         assert(value > -PI && value <= PI);
00139         return value;
00140       case ZERO_2PI:
00141         if (value >= 0) {
00142           assert(value >= 0 && value < 2*PI);
00143           return value;
00144         } else if (Rivet::isZero(value)) {
00145           value = 0.0;
00146           return value;
00147         } else {
00148           value = 2*PI + value;
00149           assert(value >= 0 && value < 2*PI);
00150           return value;
00151         }
00152       default:
00153         throw std::runtime_error("The specified phi mapping scheme is not yet implemented");
00154       }
00155     }
00156 
00157     /// Synonym for azimuthalAngle.
00158     double phi(const PhiMapping mapping = ZERO_2PI) const {
00159       return azimuthalAngle(mapping);
00160     }
00161 
00162     /// Angle subtended by the vector and the z-axis.
00163     double polarAngle() const {
00164       // Get number beween [0,PI]
00165       double polarangle = atan2(polarRadius(), z());
00166       assert(polarangle >= -PI && polarangle <= PI);
00167       return polarangle;
00168     }
00169 
00170     /// Synonym for polarAngle
00171     double theta() const {
00172       return polarAngle();
00173     }
00174 
00175     /// Purely geometric approximation to rapidity; exact for massless particles
00176     /// and in the central region.
00177     double pseudorapidity() const {
00178       return -std::log(tan( 0.5 * polarAngle() ));
00179     }
00180 
00181     /// Synonym for pseudorapidity.
00182     double eta() const {
00183       return pseudorapidity();
00184     }
00185 
00186   public:
00187     Vector3& operator*=(const double a) {
00188       _vec = multiply(a, *this)._vec;
00189       return *this;
00190     }
00191 
00192     Vector3& operator/=(const double a) {
00193       _vec = multiply(1.0/a, *this)._vec;
00194       return *this;
00195     }
00196 
00197     Vector3& operator+=(const Vector3& v) {
00198       _vec = add(*this, v)._vec;
00199       return *this;
00200     }
00201 
00202     Vector3& operator-=(const Vector3& v) {
00203       _vec = subtract(*this, v)._vec;
00204       return *this;
00205     }
00206 
00207     Vector3 operator-() const {
00208       Vector3 rtn;
00209       rtn._vec = -_vec;
00210       return rtn;
00211     }
00212 
00213   };
00214 
00215 
00216 
00217   inline double dot(const Vector3& a, const Vector3& b) {
00218     return a.dot(b);
00219   }
00220 
00221   inline Vector3 cross(const Vector3& a, const Vector3& b) {
00222     return a.cross(b);
00223   }
00224 
00225   inline Vector3 multiply(const double a, const Vector3& v) {
00226     Vector3 result;
00227     result._vec = a * v._vec;
00228     return result;
00229   }
00230 
00231   inline Vector3 multiply(const Vector3& v, const double a) {
00232     return multiply(a, v);
00233   }
00234 
00235   inline Vector3 operator*(const double a, const Vector3& v) {
00236     return multiply(a, v);
00237   }
00238 
00239   inline Vector3 operator*(const Vector3& v, const double a) {
00240     return multiply(a, v);
00241   }
00242 
00243   inline Vector3 operator/(const Vector3& v, const double a) {
00244     return multiply(1.0/a, v);
00245   }
00246 
00247   inline Vector3 add(const Vector3& a, const Vector3& b) {
00248     Vector3 result;
00249     result._vec = a._vec + b._vec;
00250     return result;
00251   }
00252 
00253   inline Vector3 subtract(const Vector3& a, const Vector3& b) {
00254     Vector3 result;
00255     result._vec = a._vec - b._vec;
00256     return result;
00257   }
00258 
00259   inline Vector3 operator+(const Vector3& a, const Vector3& b) {
00260     return add(a, b);
00261   }
00262 
00263   inline Vector3 operator-(const Vector3& a, const Vector3& b) {
00264     return subtract(a, b);
00265   }
00266 
00267   // More physicsy coordinates etc.
00268 
00269   /// Angle (in radians) between two 3-vectors.
00270   inline double angle(const Vector3& a, const Vector3& b) {
00271     return a.angle(b);
00272   }
00273 
00274   /// Calculate transverse length sq. \f$ \rho^2 \f$ of a 3-vector.
00275   inline double polarRadius2(const Vector3& v) {
00276     return v.polarRadius2();
00277   }
00278   /// Synonym for polarRadius2.
00279   inline double perp2(const Vector3& v) {
00280     return v.perp2();
00281   }
00282   /// Synonym for polarRadius2.
00283   inline double rho2(const Vector3& v) {
00284     return v.rho2();
00285   }
00286 
00287   /// Calculate transverse length \f$ \rho \f$ of a 3-vector.
00288   inline double polarRadius(const Vector3& v) {
00289     return v.polarRadius();
00290   }
00291   /// Synonym for polarRadius.
00292   inline double perp(const Vector3& v) {
00293     return v.perp();
00294   }
00295   /// Synonym for polarRadius.
00296   inline double rho(const Vector3& v) {
00297     return v.rho();
00298   }
00299 
00300 
00301   /// @brief Calculate azimuthal angle of a 3-vector.
00302   /// Returns a number in (-pi, pi] or in [0, 2pi) according to the mapping scheme selected
00303   inline double azimuthalAngle(const Vector3& v, const PhiMapping mapping = ZERO_2PI) {
00304     return v.azimuthalAngle(mapping);
00305   }
00306   /// Synonym for azimuthalAngle.
00307   inline double phi(const Vector3& v, const PhiMapping mapping = ZERO_2PI) {
00308     return v.phi(mapping);
00309   }
00310 
00311   /// Calculate polar angle of a 3-vector.
00312   inline double polarAngle(const Vector3& v) {
00313     return v.polarAngle();
00314   }
00315   /// Synonym for polarAngle.
00316   inline double theta(const Vector3& v) {
00317     return v.theta();
00318   }
00319 
00320   /// Calculate pseudorapidity of a 3-vector.
00321   inline double pseudorapidity(const Vector3& v) {
00322     return v.pseudorapidity();
00323   }
00324   /// Synonym for pseudorapidity.
00325   inline double eta(const Vector3& v) {
00326     return v.eta();
00327   }
00328 
00329 
00330   /////////////////////////////////////////////////////
00331 
00332   /// @name \f$ |\Delta eta| \f$ calculations from 3-vectors
00333   //@{
00334 
00335   /// Calculate the difference in pseudorapidity between two spatial vectors.
00336   inline double deltaEta(const Vector3& a, const Vector3& b) {
00337     return deltaEta(a.pseudorapidity(), b.pseudorapidity());
00338   }
00339 
00340   /// Calculate the difference in pseudorapidity between two spatial vectors.
00341   inline double deltaEta(const Vector3& v, double eta2) {
00342     return deltaEta(v.pseudorapidity(), eta2);
00343   }
00344 
00345   /// Calculate the difference in pseudorapidity between two spatial vectors.
00346   inline double deltaEta(double eta1, const Vector3& v) {
00347     return deltaEta(eta1, v.pseudorapidity());
00348   }
00349 
00350   //@}
00351 
00352 
00353   /// @name \f$ \Delta phi \f$ calculations from 3-vectors
00354   //@{
00355 
00356   /// Calculate the difference in azimuthal angle between two spatial vectors.
00357   inline double deltaPhi(const Vector3& a, const Vector3& b) {
00358     return deltaPhi(a.azimuthalAngle(), b.azimuthalAngle());
00359   }
00360 
00361   /// Calculate the difference in azimuthal angle between two spatial vectors.
00362   inline double deltaPhi(const Vector3& v, double phi2) {
00363     return deltaPhi(v.azimuthalAngle(), phi2);
00364   }
00365 
00366   /// Calculate the difference in azimuthal angle between two spatial vectors.
00367   inline double deltaPhi(double phi1, const Vector3& v) {
00368     return deltaPhi(phi1, v.azimuthalAngle());
00369   }
00370 
00371   //@}
00372 
00373 
00374   /// @name \f$ \Delta R \f$ calculations from 3-vectors
00375   //@{
00376 
00377   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00378   inline double deltaR(const Vector3& a, const Vector3& b) {
00379     return deltaR(a.pseudorapidity(), a.azimuthalAngle(),
00380                   b.pseudorapidity(), b.azimuthalAngle());
00381   }
00382 
00383   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00384   inline double deltaR(const Vector3& v, double eta2, double phi2) {
00385     return deltaR(v.pseudorapidity(), v.azimuthalAngle(), eta2, phi2);
00386   }
00387 
00388   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00389   inline double deltaR(double eta1, double phi1, const Vector3& v) {
00390     return deltaR(eta1, phi1, v.pseudorapidity(), v.azimuthalAngle());
00391   }
00392 
00393   //@}
00394 
00395 }
00396 
00397 #endif