Program Listing for File Vector3.h
↰ Return to documentation for file (include/crpropa/Vector3.h
)
#ifndef CRPROPA_VECTOR3_H
#define CRPROPA_VECTOR3_H
#include <iostream>
#include <cmath>
#include <vector>
#include <limits>
#include <algorithm>
namespace crpropa {
template<typename T>
class Vector3 {
public:
union {
struct
{
T x;
T y;
T z;
};
T data[3];
};
Vector3() : data{0., 0., 0.} {
}
// avoid creation of default non-conversion constructor
Vector3(const Vector3 &v) : data{v.data[0], v.data[1], v.data[2]} {
}
// Provides implicit conversion
template<typename U>
Vector3(const Vector3<U> &v) {
data[0] = v.x;
data[1] = v.y;
data[2] = v.z;
}
~Vector3()
{
}
explicit Vector3(const double *v) {
data[0] = v[0];
data[1] = v[1];
data[2] = v[2];
}
explicit Vector3(const float *v) {
data[0] = v[0];
data[1] = v[1];
data[2] = v[2];
}
explicit Vector3(const T &X, const T &Y, const T &Z) : data{X, Y, Z} {
}
explicit Vector3(T t) : data{t, t, t} {
}
void setX(const T X) {
x = X;
}
void setY(const T Y) {
y = Y;
}
void setZ(const T Z) {
z = Z;
}
void setXYZ(const T X, const T Y, const T Z) {
x = X;
y = Y;
z = Z;
}
void setR(const T r) {
*this *= r / getR();
}
void setRThetaPhi(const T r, const T theta, const T phi) {
x = r * sin(theta) * cos(phi);
y = r * sin(theta) * sin(phi);
z = r * cos(theta);
}
T getX() const {
return x;
}
T getY() const {
return y;
}
T getZ() const {
return z;
}
// magnitude (2-norm) of the vector
T getR() const {
return std::sqrt(x * x + y * y + z * z);
}
// square of magnitude of the vector
T getR2() const {
return x * x + y * y + z * z;
}
// return the azimuth angle
T getPhi() const {
T eps = std::numeric_limits < T > ::min();
if ((fabs(x) < eps) && (fabs(y) < eps))
return 0.0;
else
return std::atan2(y, x);
}
// return the zenith angle
T getTheta() const {
T eps = std::numeric_limits < T > ::min();
if ((fabs(x) < eps) && (fabs(y) < eps) && (fabs(z) < eps))
return 0.0;
else
return atan2((T) sqrt(x * x + y * y), z);
}
// return the unit-vector e_r
Vector3<T> getUnitVector() const {
return *this / getR();
}
// return the unit-vector e_theta
Vector3<T> getUnitVectorTheta() const {
T theta = getTheta();
T phi = getPhi();
return Vector3<T>(cos(theta) * cos(phi), cos(theta) * sin(phi),
-sin(theta));
}
// return the unit-vector e_phi
Vector3<T> getUnitVectorPhi() const {
return Vector3<T>(-sin(getPhi()), cos(getPhi()), 0);
}
// return the angle [0, pi] between the vectors
T getAngleTo(const Vector3<T> &v) const {
T cosdistance = dot(v) / v.getR() / getR();
// In some directions cosdistance is > 1 on some compilers
// This ensures that the correct result is returned
if (cosdistance >= 1.)
return 0;
else if (cosdistance <= -1.)
return M_PI;
else
return acos(cosdistance);
}
// return true if the angle between the vectors is smaller than a threshold
bool isParallelTo(const Vector3<T> &v, T maxAngle) const {
return getAngleTo(v) < maxAngle;
}
// linear distance to a given vector
T getDistanceTo(const Vector3<T> &point) const {
Vector3<T> d = *this - point;
return d.getR();
}
// return the component parallel to a second vector
// 0 if the second vector has 0 magnitude
Vector3<T> getParallelTo(const Vector3<T> &v) const {
T vmag = v.getR();
if (vmag == std::numeric_limits < T > ::min())
return Vector3<T>(0.);
return v * dot(v) / vmag;
}
// return the component perpendicular to a second vector
// 0 if the second vector has 0 magnitude
Vector3<T> getPerpendicularTo(const Vector3<T> &v) const {
if (v.getR() == std::numeric_limits < T > ::min())
return Vector3<T>(0.);
return (*this) - getParallelTo(v);
}
// rotate the vector around a given axis by a given angle
Vector3<T> getRotated(const Vector3<T> &axis, T angle) const {
Vector3<T> u = axis;
if (u.getR() != 0.)
u = u / u.getR();
T c = cos(angle);
T s = sin(angle);
Vector3<T> Rx(c + u.x * u.x * (1 - c), u.x * u.y * (1 - c) - u.z * s,
u.x * u.z * (1 - c) + u.y * s);
Vector3<T> Ry(u.y * u.x * (1 - c) + u.z * s, c + u.y * u.y * (1 - c),
u.y * u.z * (1 - c) - u.x * s);
Vector3<T> Rz(u.z * u.x * (1 - c) - u.y * s,
u.z * u.y * (1 - c) + u.x * s, c + u.z * u.z * (1 - c));
return Vector3<T>(dot(Rx), dot(Ry), dot(Rz));
}
// return vector with values limited to the range [lower, upper]
Vector3<T> clip(T lower, T upper) const {
Vector3<T> out;
out.x = std::max(lower, std::min(x, upper));
out.y = std::max(lower, std::min(y, upper));
out.z = std::max(lower, std::min(z, upper));
return out;
}
// return vector with absolute values
Vector3<T> abs() const {
return Vector3<T>(std::abs(x), std::abs(y), std::abs(z));
}
// return vector with floored values
Vector3<T> floor() const {
return Vector3<T>(std::floor(x), std::floor(y), std::floor(z));
}
// return vector with ceiled values
Vector3<T> ceil() const {
return Vector3<T>(std::ceil(x), std::ceil(y), std::ceil(z));
}
// minimum element
T min() const {
return std::min(x, std::min(y, z));
}
// maximum element
T max() const {
return std::max(x, std::max(y, z));
}
// dot product
T dot(const Vector3<T> &v) const {
return x * v.x + y * v.y + z * v.z;
}
// cross product
Vector3<T> cross(const Vector3<T> &v) const {
return Vector3<T>(y * v.z - v.y * z, z * v.x - v.z * x,
x * v.y - v.x * y);
}
// returns true if all elements of the two vectors are equal
bool operator ==(const Vector3<T> &v) const {
if (x != v.x)
return false;
if (y != v.y)
return false;
if (z != v.z)
return false;
return true;
}
Vector3<T> operator +(const Vector3<T> &v) const {
return Vector3(x + v.x, y + v.y, z + v.z);
}
Vector3<T> operator +(const T &f) const {
return Vector3(x + f, y + f, z + f);
}
Vector3<T> operator -(const Vector3<T> &v) const {
return Vector3(x - v.x, y - v.y, z - v.z);
}
Vector3<T> operator -(const T &f) const {
return Vector3(x - f, y - f, z - f);
}
// element-wise multiplication
Vector3<T> operator *(const Vector3<T> &v) const {
return Vector3(x * v.x, y * v.y, z * v.z);
}
Vector3<T> operator *(T v) const {
return Vector3(data[0] * v, data[1] * v, data[2] * v);
}
// element-wise division
Vector3<T> operator /(const Vector3<T> &v) const {
return Vector3(x / v.x, y / v.y, z / v.z);
}
Vector3<T> operator /(const T &f) const {
return Vector3(x / f, y / f, z / f);
}
// element-wise modulo operation
Vector3<T> operator %(const Vector3<T> &v) const {
return Vector3(fmod(x, v.x), fmod(y, v.y), fmod(z, v.z));
}
Vector3<T> operator %(const T &f) const {
return Vector3(fmod(x, f), fmod(y, f), fmod(z, f));
}
Vector3<T> &operator -=(const Vector3<T> &v) {
data[0] -= v.x;
data[1] -= v.y;
data[2] -= v.z;
return *this;
}
Vector3<T> &operator -=(const T &f) {
data[0] -= f;
data[1] -= f;
data[2] -= f;
return *this;
}
Vector3<T> &operator +=(const Vector3<T> &v) {
data[0] += v.x;
data[1] += v.y;
data[2] += v.z;
return *this;
}
Vector3<T> &operator +=(const T &f) {
data[0] += f;
data[1] += f;
data[2] += f;
return *this;
}
// element-wise multiplication
Vector3<T> &operator *=(const Vector3<T> &v) {
data[0] *= v.x;
data[1] *= v.y;
data[2] *= v.z;
return *this;
}
Vector3<T> &operator *=(const T &f) {
data[0] *= f;
data[1] *= f;
data[2] *= f;
return *this;
}
// element-wise division
Vector3<T> &operator /=(const Vector3<T> &v) {
data[0] /= v.x;
data[1] /= v.y;
data[2] /= v.z;
return *this;
}
Vector3<T> &operator /=(const T &f) {
data[0] /= f;
data[1] /= f;
data[2] /= f;
return *this;
}
// element-wise modulo operation
Vector3<T> &operator %=(const Vector3<T> &v) {
data[0] = fmod(x, v.x);
data[1] = fmod(y, v.y);
data[2] = fmod(z, v.z);
return *this;
}
Vector3<T> &operator %=(const T &f) {
data[0] = fmod(x, f);
data[1] = fmod(y, f);
data[2] = fmod(z, f);
return *this;
}
Vector3<T> &operator =(const Vector3<T> &v) {
data[0] = v.x;
data[1] = v.y;
data[2] = v.z;
return *this;
}
//Vector3<T> &operator =(Vector3<T> &&v) noexcept {
// data[0] = v.data[0];
// data[1] = v.data[1];
// data[2] = v.data[2];
// return *this;
//}
Vector3<T> &operator =(const T &f) {
data[0] = f;
data[1] = f;
data[2] = f;
return *this;
}
};
#ifndef SWIG
template<typename T>
inline std::ostream &operator <<(std::ostream &out, const Vector3<T> &v) {
out << v.x << " " << v.y << " " << v.z;
return out;
}
template<typename T>
inline std::istream &operator >>(std::istream &in, Vector3<T> &v) {
in >> v.x >> v.y >> v.z;
return in;
}
#endif
template<typename T>
inline Vector3<T> operator *(T f, const Vector3<T> &v) {
return Vector3<T>(v.x * f, v.y * f, v.z * f);
}
typedef Vector3<double> Vector3d;
typedef Vector3<float> Vector3f;
} // namespace crpropa
#endif // CRPROPA_VECTOR3_H