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 #include <cfloat>
00008 
00009 namespace Rivet {
00010 
00011 
00012   class Vector3;
00013   typedef Vector3 ThreeVector;
00014   class Matrix3;
00015 
00016   Vector3 multiply(const double, const Vector3&);
00017   Vector3 multiply(const Vector3&, const double);
00018   Vector3 add(const Vector3&, const Vector3&);
00019   Vector3 operator*(const double, const Vector3&);
00020   Vector3 operator*(const Vector3&, const double);
00021   Vector3 operator/(const Vector3&, const double);
00022   Vector3 operator+(const Vector3&, const Vector3&);
00023   Vector3 operator-(const Vector3&, const Vector3&);
00024 
00025 
00026   /// @brief Three-dimensional specialisation of Vector.
00027   class Vector3 : public Vector<3> {
00028 
00029     friend class Matrix3;
00030     friend Vector3 multiply(const double, const Vector3&);
00031     friend Vector3 multiply(const Vector3&, const double);
00032     friend Vector3 add(const Vector3&, const Vector3&);
00033     friend Vector3 subtract(const Vector3&, const Vector3&);
00034 
00035   public:
00036     Vector3() : Vector<3>() { }
00037 
00038     template<typename V3>
00039     Vector3(const V3& other) {
00040       this->setX(other.x());
00041       this->setY(other.y());
00042       this->setZ(other.z());
00043     }
00044 
00045     Vector3(const Vector<3>& other) {
00046       this->setX(other.get(0));
00047       this->setY(other.get(1));
00048       this->setZ(other.get(2));
00049     }
00050 
00051     Vector3(double x, double y, double z) {
00052       this->setX(x);
00053       this->setY(y);
00054       this->setZ(z);
00055     }
00056 
00057     ~Vector3() { }
00058 
00059   public:
00060     static Vector3 mkX() { return Vector3(1,0,0); }
00061     static Vector3 mkY() { return Vector3(0,1,0); }
00062     static Vector3 mkZ() { return Vector3(0,0,1); }
00063 
00064   public:
00065     double x() const { return get(0); }
00066     double y() const { return get(1); }
00067     double z() const { return get(2); }
00068     Vector3& setX(double x) { set(0, x); return *this; }
00069     Vector3& setY(double y) { set(1, y); return *this; }
00070     Vector3& setZ(double z) { set(2, z); return *this; }
00071 
00072     double dot(const Vector3& v) const {
00073       return _vec.dot(v._vec);
00074     }
00075 
00076     Vector3 cross(const Vector3& v) const {
00077       Vector3 result;
00078       result._vec = _vec.cross(v._vec);
00079       return result;
00080     }
00081 
00082     double angle(const Vector3& v) const {
00083       const double localDotOther = unit().dot(v.unit());
00084       if (localDotOther > 1.0) return 0.0;
00085       if (localDotOther < -1.0) return M_PI;
00086       return acos(localDotOther);
00087     }
00088 
00089     Vector3 unit() const {
00090       /// @todo What to do in this situation?
00091       if (isZero()) return *this;
00092       else return *this * 1.0/this->mod();
00093     }
00094 
00095     double polarRadius2() const {
00096       return x()*x() + y()*y();
00097     }
00098 
00099     /// Synonym for polarRadius2
00100     double perp2() const {
00101       return polarRadius2();
00102     }
00103 
00104     /// Synonym for polarRadius2
00105     double rho2() const {
00106       return polarRadius2();
00107     }
00108 
00109     double polarRadius() const {
00110       return sqrt(polarRadius2());
00111     }
00112 
00113     /// Synonym for polarRadius
00114     double perp() const {
00115       return polarRadius();
00116     }
00117 
00118     /// Synonym for polarRadius
00119     double rho() const {
00120       return polarRadius();
00121     }
00122 
00123     /// Angle subtended by the vector's projection in x-y and the x-axis.
00124     double azimuthalAngle(const PhiMapping mapping = ZERO_2PI) const {
00125       // If this is a null vector, return zero rather than let atan2 set an error state
00126       if (Rivet::isZero(mod2())) return 0.0;
00127 
00128       // Calculate the arctan and return in the requested range
00129       const double value = atan2( y(), x() );
00130       return mapAngle(value, mapping);
00131     }
00132 
00133     /// Synonym for azimuthalAngle.
00134     double phi(const PhiMapping mapping = ZERO_2PI) const {
00135       return azimuthalAngle(mapping);
00136     }
00137 
00138     /// Angle subtended by the vector and the z-axis.
00139     double polarAngle() const {
00140       // Get number beween [0,PI]
00141       const double polarangle = atan2(polarRadius(), z());
00142       return mapAngle0ToPi(polarangle);
00143     }
00144 
00145     /// Synonym for polarAngle
00146     double theta() const {
00147       return polarAngle();
00148     }
00149 
00150     /// Purely geometric approximation to rapidity; exact for massless particles
00151     /// and in the central region.
00152     // cut-off such that |eta| < log(2/DBL_EPSILON)
00153     double pseudorapidity() const {
00154       const double epsilon = DBL_EPSILON;
00155       double m = mod();
00156       if ( m == 0.0 ) return  0.0;
00157       double pt = max(epsilon*m, perp());
00158       double rap = std::log((m + fabs(z()))/pt);
00159       return z() > 0.0 ? rap: -rap;
00160     }
00161 
00162     /// Synonym for pseudorapidity.
00163     double eta() const {
00164       return pseudorapidity();
00165     }
00166 
00167   public:
00168     Vector3& operator*=(const double a) {
00169       _vec = multiply(a, *this)._vec;
00170       return *this;
00171     }
00172 
00173     Vector3& operator/=(const double a) {
00174       _vec = multiply(1.0/a, *this)._vec;
00175       return *this;
00176     }
00177 
00178     Vector3& operator+=(const Vector3& v) {
00179       _vec = add(*this, v)._vec;
00180       return *this;
00181     }
00182 
00183     Vector3& operator-=(const Vector3& v) {
00184       _vec = subtract(*this, v)._vec;
00185       return *this;
00186     }
00187 
00188     Vector3 operator-() const {
00189       Vector3 rtn;
00190       rtn._vec = -_vec;
00191       return rtn;
00192     }
00193 
00194   };
00195 
00196 
00197 
00198   inline double dot(const Vector3& a, const Vector3& b) {
00199     return a.dot(b);
00200   }
00201 
00202   inline Vector3 cross(const Vector3& a, const Vector3& b) {
00203     return a.cross(b);
00204   }
00205 
00206   inline Vector3 multiply(const double a, const Vector3& v) {
00207     Vector3 result;
00208     result._vec = a * v._vec;
00209     return result;
00210   }
00211 
00212   inline Vector3 multiply(const Vector3& v, const double a) {
00213     return multiply(a, v);
00214   }
00215 
00216   inline Vector3 operator*(const double a, const Vector3& v) {
00217     return multiply(a, v);
00218   }
00219 
00220   inline Vector3 operator*(const Vector3& v, const double a) {
00221     return multiply(a, v);
00222   }
00223 
00224   inline Vector3 operator/(const Vector3& v, const double a) {
00225     return multiply(1.0/a, v);
00226   }
00227 
00228   inline Vector3 add(const Vector3& a, const Vector3& b) {
00229     Vector3 result;
00230     result._vec = a._vec + b._vec;
00231     return result;
00232   }
00233 
00234   inline Vector3 subtract(const Vector3& a, const Vector3& b) {
00235     Vector3 result;
00236     result._vec = a._vec - b._vec;
00237     return result;
00238   }
00239 
00240   inline Vector3 operator+(const Vector3& a, const Vector3& b) {
00241     return add(a, b);
00242   }
00243 
00244   inline Vector3 operator-(const Vector3& a, const Vector3& b) {
00245     return subtract(a, b);
00246   }
00247 
00248   // More physicsy coordinates etc.
00249 
00250   /// Angle (in radians) between two 3-vectors.
00251   inline double angle(const Vector3& a, const Vector3& b) {
00252     return a.angle(b);
00253   }
00254 
00255   /////////////////////////////////////////////////////
00256 
00257   /// @name \f$ |\Delta eta| \f$ calculations from 3-vectors
00258   //@{
00259 
00260   /// Calculate the difference in pseudorapidity between two spatial vectors.
00261   inline double deltaEta(const Vector3& a, const Vector3& b) {
00262     return deltaEta(a.pseudorapidity(), b.pseudorapidity());
00263   }
00264 
00265   /// Calculate the difference in pseudorapidity between two spatial vectors.
00266   inline double deltaEta(const Vector3& v, double eta2) {
00267     return deltaEta(v.pseudorapidity(), eta2);
00268   }
00269 
00270   /// Calculate the difference in pseudorapidity between two spatial vectors.
00271   inline double deltaEta(double eta1, const Vector3& v) {
00272     return deltaEta(eta1, v.pseudorapidity());
00273   }
00274 
00275   //@}
00276 
00277 
00278   /// @name \f$ \Delta phi \f$ calculations from 3-vectors
00279   //@{
00280 
00281   /// Calculate the difference in azimuthal angle between two spatial vectors.
00282   inline double deltaPhi(const Vector3& a, const Vector3& b) {
00283     return deltaPhi(a.azimuthalAngle(), b.azimuthalAngle());
00284   }
00285 
00286   /// Calculate the difference in azimuthal angle between two spatial vectors.
00287   inline double deltaPhi(const Vector3& v, double phi2) {
00288     return deltaPhi(v.azimuthalAngle(), phi2);
00289   }
00290 
00291   /// Calculate the difference in azimuthal angle between two spatial vectors.
00292   inline double deltaPhi(double phi1, const Vector3& v) {
00293     return deltaPhi(phi1, v.azimuthalAngle());
00294   }
00295 
00296   //@}
00297 
00298 
00299   /// @name \f$ \Delta R \f$ calculations from 3-vectors
00300   //@{
00301 
00302   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00303   inline double deltaR(const Vector3& a, const Vector3& b) {
00304     return deltaR(a.pseudorapidity(), a.azimuthalAngle(),
00305                   b.pseudorapidity(), b.azimuthalAngle());
00306   }
00307 
00308   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00309   inline double deltaR(const Vector3& v, double eta2, double phi2) {
00310     return deltaR(v.pseudorapidity(), v.azimuthalAngle(), eta2, phi2);
00311   }
00312 
00313   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
00314   inline double deltaR(double eta1, double phi1, const Vector3& v) {
00315     return deltaR(eta1, phi1, v.pseudorapidity(), v.azimuthalAngle());
00316   }
00317 
00318   //@}
00319 
00320 }
00321 
00322 #endif