// // ******************************************************************** // * This Software is part of the AIDA Unified Solids Library package * // * See: https://aidasoft.web.cern.ch/USolids * // ******************************************************************** // // $Id:$ // // -------------------------------------------------------------------- // // UVector2 // // Class description: // // UVector2 is a general 2-vector class defining vectors in two // dimension using double components. // // 19.09.12 Marek Gayer // Created from original implementation in CLHEP // -------------------------------------------------------------------- #ifndef UVECTOR2_H #define UVECTOR2_H #include <cmath> #include <iostream> #include "UVector3.hh" // Declarations of classes and global methods class UVector2; std::ostream& operator << (std::ostream&, const UVector2&); //std::istream & operator >> (std::istream &, UVector2 &); inline double operator * (const UVector2& a, const UVector2& b); inline UVector2 operator * (const UVector2& p, double a); inline UVector2 operator * (double a, const UVector2& p); UVector2 operator / (const UVector2& p, double a); inline UVector2 operator + (const UVector2& a, const UVector2& b); inline UVector2 operator - (const UVector2& a, const UVector2& b); /** * @author * @ingroup vector */ class UVector2 { public: enum { X = 0, Y = 1, NUM_COORDINATES = 2, SIZE = NUM_COORDINATES }; // Safe indexing of the coordinates when using with matrices, arrays, etc. inline UVector2(double x = 0.0, double y = 0.0); // The constructor. inline UVector2(const UVector2& p); // The copy constructor. explicit UVector2(const UVector3& s); // "demotion" constructor" // WARNING -- THIS IGNORES THE Z COMPONENT OF THE UVector3. // SO IN GENERAL, UVector2(v)==v WILL NOT HOLD! inline ~UVector2(); // The destructor. // inline double x() const; // inline double y() const; // The components in cartesian coordinate system. double operator()(int i) const; inline double operator [](int i) const; // Get components by index. 0-based. double& operator()(int i); inline double& operator [](int i); // Set components by index. 0-based. inline void setX(double x); inline void setY(double y); inline void set(double x, double y); // Set the components in cartesian coordinate system. inline double phi() const; // The azimuth angle. inline double mag2() const; // The magnitude squared. inline double mag() const; // The magnitude. inline double r() const; // r in polar coordinates (r, phi): equal to mag(). inline void setPhi(double phi); // Set phi keeping mag constant. inline void setMag(double r); // Set magnitude keeping phi constant. inline void setR(double r); // Set R keeping phi constant. Same as setMag. inline void setPolar(double r, double phi); // Set by polar coordinates. inline UVector2& operator = (const UVector2& p); // Assignment. inline bool operator == (const UVector2& v) const; inline bool operator != (const UVector2& v) const; // Comparisons. int compare(const UVector2& v) const; bool operator > (const UVector2& v) const; bool operator < (const UVector2& v) const; bool operator>= (const UVector2& v) const; bool operator<= (const UVector2& v) const; // dictionary ordering according to y, then x component static inline double getTolerance(); static double setTolerance(double tol); double howNear(const UVector2& p) const; bool isNear(const UVector2& p, double epsilon = tolerance) const; double howParallel(const UVector2& p) const; bool isParallel (const UVector2& p, double epsilon = tolerance) const; double howOrthogonal(const UVector2& p) const; bool isOrthogonal (const UVector2& p, double epsilon = tolerance) const; inline UVector2& operator += (const UVector2& p); // Addition. inline UVector2& operator -= (const UVector2& p); // Subtraction. inline UVector2 operator - () const; // Unary minus. inline UVector2& operator *= (double a); // Scaling with real numbers. inline UVector2 unit() const; // Unit vector parallel to this. inline UVector2 orthogonal() const; // Vector orthogonal to this. inline double dot(const UVector2& p) const; // Scalar product. inline double angle(const UVector2&) const; // The angle w.r.t. another 2-vector. void rotate(double); // Rotates the UVector2. operator UVector3() const; // Cast a UVector2 as a UVector3. // The remaining methods are friends, thus defined at global scope: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - friend std::ostream& operator<< (std::ostream&, const UVector2&); // Output to a stream. inline friend double operator * (const UVector2& a, const UVector2& b); // Scalar product. inline friend UVector2 operator * (const UVector2& p, double a); // v*c inline friend UVector2 operator * (double a, const UVector2& p); // c*v friend UVector2 operator / (const UVector2& p, double a); // v/c inline friend UVector2 operator + (const UVector2& a, const UVector2& b); // v1+v2 inline friend UVector2 operator - (const UVector2& a, const UVector2& b); // v1-v2 enum { ZMpvToleranceTicks = 100 }; double x; double y; // The components. private: static double tolerance; // default tolerance criterion for isNear() to return true. }; // UVector2 static const UVector2 X_HAT2(1.0, 0.0); static const UVector2 Y_HAT2(0.0, 1.0); /* inline double UVector2::x() const { return x; } inline double UVector2::y() const { return y; } */ inline UVector2::UVector2(double x1, double y1) : x(x1), y(y1) {} inline UVector2::UVector2(const UVector3& s) : x(s.x), y(s.y) {} inline void UVector2::setX(double x1) { x = x1; } inline void UVector2::setY(double y1) { y = y1; } inline void UVector2::set(double x1, double y1) { x = x1; y = y1; } double& UVector2::operator[](int i) { return operator()(i); } double UVector2::operator[](int i) const { return operator()(i); } inline UVector2::UVector2(const UVector2& p) : x(p.x), y(p.y) {} inline UVector2::~UVector2() {} inline UVector2& UVector2::operator = (const UVector2& p) { if (this == &p) { return *this; } x = p.x; y = p.y; return *this; } inline bool UVector2::operator == (const UVector2& v) const { return (v.x == x && v.y == y) ? true : false; } inline bool UVector2::operator != (const UVector2& v) const { return (v.x != x || v.y != y) ? true : false; } inline UVector2& UVector2::operator += (const UVector2& p) { x += p.x; y += p.y; return *this; } inline UVector2& UVector2::operator -= (const UVector2& p) { x -= p.x; y -= p.y; return *this; } inline UVector2 UVector2::operator - () const { return UVector2(-x, -y); } inline UVector2& UVector2::operator *= (double a) { x *= a; y *= a; return *this; } inline double UVector2::dot(const UVector2& p) const { return x * p.x + y * p.y; } inline double UVector2::mag2() const { return x * x + y * y; } inline double UVector2::mag() const { return std::sqrt(mag2()); } inline double UVector2::r() const { return std::sqrt(mag2()); } inline UVector2 UVector2::unit() const { double tot = mag2(); UVector2 p(*this); return tot > 0.0 ? p *= (1.0 / std::sqrt(tot)) : UVector2(1, 0); } inline UVector2 UVector2::orthogonal() const { double x1 = std::fabs(x), y1 = std::fabs(y); if (x1 < y1) { return UVector2(y, -x); } else { return UVector2(-y, x); } } inline double UVector2::phi() const { return x == 0.0 && y == 0.0 ? 0.0 : std::atan2(y, x); } inline double UVector2::angle(const UVector2& q) const { double ptot2 = mag2() * q.mag2(); return ptot2 <= 0.0 ? 0.0 : std::acos(dot(q) / std::sqrt(ptot2)); } inline void UVector2::setMag(double r1) { double ph = phi(); setX(r1 * std::cos(ph)); setY(r1 * std::sin(ph)); } inline void UVector2::setR(double r1) { setMag(r1); } inline void UVector2::setPhi(double phi1) { double ma = mag(); setX(ma * std::cos(phi1)); setY(ma * std::sin(phi1)); } inline void UVector2::setPolar(double r1, double phi1) { setX(r1 * std::cos(phi1)); setY(r1 * std::sin(phi1)); } inline UVector2 operator + (const UVector2& a, const UVector2& b) { return UVector2(a.x + b.x, a.y + b.y); } inline UVector2 operator - (const UVector2& a, const UVector2& b) { return UVector2(a.x - b.x, a.y - b.y); } inline UVector2 operator * (const UVector2& p, double a) { return UVector2(a * p.x, a * p.y); } inline UVector2 operator * (double a, const UVector2& p) { return UVector2(a * p.x, a * p.y); } inline double operator * (const UVector2& a, const UVector2& b) { return a.dot(b); } inline double UVector2::getTolerance() { return tolerance; } #endif /* UVECTOR2_H */