Skip to content

File NPVector2D.h

File List > core > NPVector2D.h

Go to the documentation of this file

#ifndef NPVector2D_h
#define NPVector2D_h
#include "NPCoordinateType.h"
#include <iostream>
namespace nptool {

  template <typename T> class Vector2D {
   public:
    Vector2D() : m_A(0), m_B(0), m_coord(cartesian){};
    Vector2D(T A, T B, coord_type type = cartesian) : m_A(A), m_B(B), m_coord(type){};
    ~Vector2D(){};

   private:
    T m_A;
    T m_B;
    coord_type m_coord;

   public:
    inline void SetXY(T X, T Y) {
      m_coord = cartesian;
      m_A = X;
      m_B = Y;
    };
    inline void SetRPhi(T R, T Phi) {
      m_coord = polar;
      m_A = R;
      m_B = Phi;
    };

    inline const coord_type GetCoordinateSystem() { return m_coord; }

    inline T X() const {
      if (m_coord == cartesian)
        return m_A;
      else {
        return (m_A * cos(m_B));
      }
    };
    inline T Y() const {
      if (m_coord == cartesian)
        return m_B;
      else {
        return (m_A * sin(m_B));
      }
    };
    inline T R() const {
      if (m_coord == polar)
        return m_A;
      else {
        return sqrt(m_A * m_A + m_B * m_B);
      }
    }
    inline T Phi() const {
      if (m_coord == polar)
        return m_B;
      else {
        return atan(m_A * m_A + m_B * m_B);
      }
    }
    inline Vector2D<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 Vector2D<TO>& right) { return (X() * right.X()) + (Y() * right.Y()); }
    template <typename TO> T cross(const Vector2D<TO>& right) { return (X() * right.Y()) - (Y() * right.X()); }
    // Operator
    friend std::ostream& operator<<(std::ostream& os, const Vector2D<T>& v) {
      if (v.m_coord == cartesian)
        os << "(X=" << v.m_A << ";Y=" << v.m_B << ")";
      else
        os << "(R=" << v.m_A << ";P=" << v.m_B << ")";

      return os;
    }

    // Add
    template <typename TO> friend Vector2D<T> operator+(const Vector2D<T>& left, const Vector2D<TO>& right) {
      return Vector2D<T>(left.X() + right.X(), left.Y() + right.Y(), cartesian);
    }
    template <typename TO> friend Vector2D<T>& operator+=(Vector2D<T>& left, const Vector2D<TO>& right) {
      auto X0 = left.X() + right.X();
      auto Y0 = left.Y() + right.Y();
      left.m_coord = cartesian;
      left.m_A = X0;
      left.m_B = Y0;
      return left;
    }

    // Substract
    template <typename TO> friend Vector2D<T> operator-(const Vector2D<T>& left, const Vector2D<TO>& right) {
      return Vector2D<T>(left.X() - right.X(), left.Y() - right.Y(), cartesian);
    }

    template <typename TO> friend Vector2D<T>& operator-=(Vector2D<T>& left, const Vector2D<TO>& right) {
      auto X0 = left.X() - right.X();
      auto Y0 = left.Y() - right.Y();
      left.m_coord = cartesian;
      left.m_A = X0;
      left.m_B = Y0;
      return left;
    }

    // Scale
    template <typename TO> friend Vector2D<T>& operator*=(Vector2D<T>& left, const TO right) {
      left.m_A *= right;
      if (left.m_coord == cartesian) {
        left.m_B *= right;
      }
      return left;
    }
    template <typename TO> friend Vector2D<T>& operator/=(Vector2D<T>& left, const TO right) {
      left.m_A /= right;
      if (left.m_coord == cartesian) {
        left.m_B /= right;
      }
      return left;
    }
  };

} // namespace nptool
#endif