File NPVector3D.h
File List > core > NPVector3D.h
Go to the documentation of this file
#ifndef NPVector3D_h
#define NPVector3D_h
#include "NPCoordinateType.h"
#include <iostream>
namespace nptool {
template <typename T> class Vector3D {
public:
Vector3D() : m_A(0), m_B(0), m_C(0), m_coord(cartesian){};
Vector3D(T A, T B, T C, coord_type type = cartesian) : m_A(A), m_B(B), m_C(C), m_coord(type){};
~Vector3D(){};
private:
T m_A;
T m_B;
T m_C;
coord_type m_coord;
public:
inline void SetXYZ(T X, T Y, T Z) {
m_coord = cartesian;
m_A = X;
m_B = Y;
m_C = Z;
};
inline void SetRThetaPhi(T R, T Theta, T Phi) {
m_coord = polar;
m_A = R;
m_B = Theta;
m_C = Phi;
};
inline const coord_type GetCoordinateSystem() { return m_coord; }
inline T X() const {
if (m_coord == cartesian)
return m_A;
else if (m_coord == cylindrical) {
return (m_A * cos(m_B));
}
else {
return (m_A * sin(m_B) * cos(m_C));
}
};
inline T Y() const {
if (m_coord == cartesian)
return m_B;
else if (m_coord == cylindrical) {
return (m_A * sin(m_B));
}
else {
return (m_A * sin(m_B) * sin(m_C));
}
};
inline T Z() const {
if (m_coord == cartesian || m_coord == cylindrical)
return m_C;
else {
return (m_A * cos(m_B));
}
};
inline T R() const {
if (m_coord == polar)
return m_A;
else {
return sqrt(m_A * m_A + m_B * m_B + m_C * m_C);
}
}
inline T Phi() const {
if (m_coord == polar)
return m_B;
else {
return atan(m_A * m_A + m_B * m_B);
}
}
inline Vector3D<T> Unit() const {
auto result = *this;
if (result.m_coord == polar) {
result.m_A = 1;
}
else {
auto R0 = R();
result.m_A /= R0;
result.m_B /= R0;
}
return result;
}
inline void to_polar() {
if (m_coord == polar)
return;
else {
auto R0 = R();
m_B = Phi();
m_A = R0;
m_coord = polar;
}
return;
}
inline void to_cartesian() {
if (m_coord == cartesian)
return;
else {
auto X0 = X();
m_B = Y();
m_A = X0;
m_coord = cartesian;
}
return;
}
template <typename TO> T dot(const Vector3D<TO>& right) { return (X() * right.X()) + (Y() * right.Y()); }
template <typename TO> Vector3D<T> cross(const Vector3D<TO>& B) {
return Vector3D<T>(Y() * B.Z() - Z() * B.Y(), Z() * B.X() - X() * B.Z(), X() * B.Y() - Y() * B.X());
}
// Operator
friend std::ostream& operator<<(std::ostream& os, const Vector3D<T>& v) {
if (v.m_coord == cartesian)
os << "(X=" << v.m_A << ";Y=" << v.m_B << ";Z=" << v.m_C << ")";
else
os << "(R=" << v.m_A << ";P=" << v.m_B << ")";
return os;
}
// Add
template <typename TO> friend Vector3D<T> operator+(const Vector3D<T>& left, const Vector3D<TO>& right) {
return Vector3D<T>(left.X() + right.X(), left.Y() + right.Y(), left.Z() + left.Z(), cartesian);
}
template <typename TO> friend Vector3D<T>& operator+=(Vector3D<T>& left, const Vector3D<TO>& right) {
auto X0 = left.X() + right.X();
auto Y0 = left.Y() + right.Y();
auto Z0 = left.Z() + right.Z();
left.m_coord = cartesian;
left.m_A = X0;
left.m_B = Y0;
left.m_C = Z0;
return left;
}
// Substract
template <typename TO> friend Vector3D<T> operator-(const Vector3D<T>& left, const Vector3D<TO>& right) {
return Vector3D<T>(left.X() - right.X(), left.Y() - right.Y(), left.Z() - right.Z(), cartesian);
}
template <typename TO> friend Vector3D<T>& operator-=(Vector3D<T>& left, const Vector3D<TO>& right) {
auto X0 = left.X() - right.X();
auto Y0 = left.Y() - right.Y();
auto Z0 = left.Z() - right.Z();
left.m_coord = cartesian;
left.m_A = X0;
left.m_B = Y0;
left.m_C = Z0;
return left;
}
// Scale
template <typename TO> friend Vector3D<T>& operator*=(Vector3D<T>& left, const TO right) {
left.m_A *= right;
if (left.m_coord == cartesian) {
left.m_B *= right;
}
return left;
}
template <typename TO> friend Vector3D<T>& operator/=(Vector3D<T>& left, TO right) {
left.m_A /= right;
if (left.m_coord == cartesian) {
left.m_B /= right;
}
return left;
}
};
} // namespace nptool
#endif