Skip to content

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