etk/etk/math/Vector2D.h

429 lines
12 KiB
C++

/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/math/Vector3D.h>
#include <etk/types.h>
#pragma once
#include <math.h>
namespace etk {
template <typename T> class Vector2D {
public:
T m_floats[2];
public:
/* ****************************************************
* Constructor
*****************************************************/
Vector2D() {
#ifdef DEBUG
// in debug mode we set supid value to prevent forget of the inits ...
m_floats[0] = (T)34673363;
m_floats[1] = (T)34523535;
#endif
};
Vector2D(T _x, T _y) {
m_floats[0] = _x;
m_floats[1] = _y;
};
Vector2D(const Vector2D<double>& _obj) {
m_floats[0] = (T)_obj.x();
m_floats[1] = (T)_obj.y();
};
Vector2D(const Vector2D<float>& _obj) {
m_floats[0] = (T)_obj.x();
m_floats[1] = (T)_obj.y();
};
Vector2D(const Vector2D<int32_t>& _obj) {
m_floats[0] = (T)_obj.x();
m_floats[1] = (T)_obj.y();
};
Vector2D(const std::string& _str);
#if __CPP_VERSION__ >= 2011
Vector2D(const std::u32string& _str);
#endif
~Vector2D() { };
/* ****************************************************
* = assigment
*****************************************************/
const Vector2D<T>& operator= (const Vector2D<T>& _obj ) {
m_floats[0] = _obj.m_floats[0];
m_floats[1] = _obj.m_floats[1];
return *this;
}
const Vector2D<T>& operator= (const T _val ) {
m_floats[0] = _val;
m_floats[1] = _val;
return *this;
}
/* ****************************************************
* == operator
*****************************************************/
bool operator== (const Vector2D<T>& _obj) const {
return ( (T)_obj.m_floats[0] == m_floats[0]
&& (T)_obj.m_floats[1] == m_floats[1]);
}
/* ****************************************************
* != operator
*****************************************************/
bool operator!= (const Vector2D<T>& _obj) const {
return ( (T)_obj.m_floats[0] != m_floats[0]
|| (T)_obj.m_floats[1] != m_floats[1]);
}
/* ****************************************************
* += operator
*****************************************************/
const Vector2D<T>& operator+= (const Vector2D<T>& _obj) {
m_floats[0] += _obj.m_floats[0];
m_floats[1] += _obj.m_floats[1];
return *this;
}
const Vector2D<T>& operator+= (const T _val) {
m_floats[0] += _val;
m_floats[1] += _val;
return *this;
}
/* ****************************************************
* + operator
*****************************************************/
Vector2D<T> operator+ (const Vector2D<T>& _obj) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] += _obj.m_floats[0];
tmpp.m_floats[1] += _obj.m_floats[1];
return tmpp;
}
Vector2D<T> operator+ (const T _val) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] += _val;
tmpp.m_floats[1] += _val;
return tmpp;
}
/* ****************************************************
* -= operator
*****************************************************/
const Vector2D<T>& operator-= (const Vector2D<T>& _obj) {
m_floats[0] -= _obj.m_floats[0];
m_floats[1] -= _obj.m_floats[1];
return *this;
}
const Vector2D<T>& operator-= (const T _val) {
m_floats[0] -= _val;
m_floats[1] -= _val;
return *this;
}
/* ****************************************************
* - operator
*****************************************************/
Vector2D<T> operator- (const Vector2D<T>& _obj) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] -= _obj.m_floats[0];
tmpp.m_floats[1] -= _obj.m_floats[1];
return tmpp;
}
Vector2D<T> operator- (const T _val) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] -= _val;
tmpp.m_floats[1] -= _val;
return tmpp;
}
/* ****************************************************
* *= operator
*****************************************************/
const Vector2D<T>& operator*= (const Vector2D<T>& _obj) {
m_floats[0] *= _obj.m_floats[0];
m_floats[1] *= _obj.m_floats[1];
return *this;
}
const Vector2D<T>& operator*= (const T _val) {
m_floats[0] *= _val;
m_floats[1] *= _val;
return *this;
}
/* ****************************************************
* * operator
*****************************************************/
Vector2D<T> operator* (const Vector2D<T>& _obj) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] *= _obj.m_floats[0];
tmpp.m_floats[1] *= _obj.m_floats[1];
return tmpp;
}
Vector2D<T> operator* (const T _val) const {
Vector2D<T> tmpp(m_floats[0],m_floats[1]);
tmpp.m_floats[0] *= _val;
tmpp.m_floats[1] *= _val;
return tmpp;
}
/* ****************************************************
* / operator
*****************************************************/
Vector2D<T> operator/ (const Vector2D<T>& _obj) const{
Vector2D<T> tmpp(m_floats[0], m_floats[1]);
tmpp.m_floats[0] /= _obj.m_floats[0];
tmpp.m_floats[1] /= _obj.m_floats[1];
return tmpp;
}
Vector2D<T> operator/ (const T _val) const {
Vector2D<T> tmpp(m_floats[0], m_floats[1]);
tmpp.m_floats[0] /= _val;
tmpp.m_floats[1] /= _val;
return tmpp;
}
/* ****************************************************
* / operator
*****************************************************/
const Vector2D<T>& operator/= (const Vector2D<T>& _obj) {
m_floats[0] /= _obj.m_floats[0];
m_floats[1] /= _obj.m_floats[1];
return *this;
}
const Vector2D<T>& operator/= (const T _val) {
m_floats[0] /= _val;
m_floats[1] /= _val;
return *this;
}
/* ****************************************************
* ++ operator
*****************************************************/
Vector2D<T>& operator++() {
++m_floats[0];
++m_floats[1];
return *this;
}
Vector2D<T> operator++(int _unused) {
Vector2D<T> result = *this;
++(*this);
return result;
}
/* ****************************************************
* -- operator
*****************************************************/
Vector2D<T>& operator--() {
--m_floats[0];
--m_floats[1];
return *this;
}
Vector2D<T> operator--(int _unused) {
Vector2D<T> result = *this;
--(*this);
return result;
}
/**
* @brief Return the cross product / determinant
* @param _obj The other vector in the cross product
*/
T cross(const Vector2D<T>& _obj) const {
return m_floats[0] * _obj.m_floats[1]
- m_floats[1] * _obj.m_floats[0];
}
/**
* @brief Return the dot product
* @param _obj The other vector in the dot product
*/
T dot(const Vector2D<T>& _obj) const {
return m_floats[0] * _obj.m_floats[0]
+ m_floats[1] * _obj.m_floats[1];
}
/**
* @brief Return the length of the vector squared
*/
T length2() const {
return dot(*this);
}
/**
* @brief Return the length of the vector
*/
float length() const {
#if __CPP_VERSION__ >= 2011 && !defined(__STDCPP_LLVM__)
return std::sqrt(length2());
#else
return sqrt(length2());
#endif
}
/**
* @brief Return the distance squared between the ends of this and another vector
* This is symantically treating the vector like a point
*/
T distance2(const Vector2D<T>& _obj) const {
return (_obj - *this).length2();
}
/**
* @brief Return the distance between the ends of this and another vector
* This is symantically treating the vector like a point
*/
float distance(const Vector2D<T>& _obj) const {
return (_obj - *this).length();
}
/**
* @brief Normalize this vector
* x^2 + y^2 + z^2 = 1
*/
Vector2D<T>& normalize() {
*this /= length();
return *this;
}
/**
* @brief Normalize this vector
* x^2 + y^2 + z^2 = 1
*/
Vector2D<T>& safeNormalize() {
T tmp = length();
if (tmp != 0) {
*this /= length();
}
return *this;
}
/**
* @brief Return a normalized version of this vector
*/
Vector2D<T> normalized() const {
return *this / length();
}
/**
* @brief Return a vector will the absolute values of each element
*/
Vector2D<T> absolute() const {
return Vector2D<T>( abs(m_floats[0]),
abs(m_floats[1]));
}
/**
* @brief Return the axis with the smallest value
* Note return values are 0,1,2 for x, y, or z
*/
int32_t minAxis() const {
return m_floats[0] < m_floats[1] ? 0 : 1;
}
/**
* @brief Return the axis with the largest value
* Note return values are 0,1,2 for x, y, or z
*/
int32_t maxAxis() const {
return m_floats[0] < m_floats[1] ? 1 : 0;
}
int32_t furthestAxis() const {
return absolute().minAxis();
}
int32_t closestAxis() const {
return absolute().maxAxis();
}
/**
* @brief Return the x value
*/
const T& getX() const {
return m_floats[0];
}
/**
* @brief Return the y value
*/
const T& getY() const {
return m_floats[1];
}
/**
* @brief Set the x value
*/
void setX(T _x) {
m_floats[0] = _x;
};
/**
* @brief Set the y value
*/
void setY(T _y) {
m_floats[1] = _y;
};
/**
* @brief Return the x value
*/
const T& x() const {
return m_floats[0];
}
/**
* @brief Return the y value
*/
const T& y() const {
return m_floats[1];
}
operator T *() {
return &m_floats[0];
}
operator const T *() const {
return &m_floats[0];
}
/**
* @brief Set each element to the max of the current values and the values of another vector
* @param _other The other vector to compare with
*/
void setMax(const Vector2D<T>& _other) {
m_floats[0] = std::max(m_floats[0], _other.m_floats[0]);
m_floats[1] = std::max(m_floats[1], _other.m_floats[1]);
}
/**
* @brief Set each element to the min of the current values and the values of another vector
* @param _other The other vector to compare with
*/
void setMin(const Vector2D<T>& _other) {
m_floats[0] = std::min(m_floats[0], _other.m_floats[0]);
m_floats[1] = std::min(m_floats[1], _other.m_floats[1]);
}
void setValue(const T& _xxx, const T& _yyy) {
m_floats[0] = _xxx;
m_floats[1] = _yyy;
}
void setZero() {
setValue(0,0);
}
bool isZero() const {
return m_floats[0] == 0
&& m_floats[1] == 0;
}
//!< string cast :
operator std::string() const;
#if __CPP_VERSION__ >= 2011
operator std::u32string() const;
#endif
};
/**
* @brief Debug operator To display the curent element in a Human redeable information
*/
std::ostream& operator <<(std::ostream& _os, const etk::Vector2D<int32_t>& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const etk::Vector2D<float>& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const etk::Vector2D<uint32_t>& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const etk::Vector2D<bool>& _obj);
};
// To siplify the writing of the code ==> this permit to have the same name with the glsl language...
using vec2 = etk::Vector2D<float>;
using ivec2 = etk::Vector2D<int32_t>;
// not compatible with glsl ... but it is better to have a same writing
using uivec2 = etk::Vector2D<uint32_t>;
using bvec2 = etk::Vector2D<bool>;
inline vec2 vec2ClipInt32(const vec2& _val) {
return vec2((int32_t)_val.x(), (int32_t)_val.y());
}
inline vec2 vec2ClipInt64(const vec2& _val) {
return vec2((int64_t)_val.x(), (int64_t)_val.y());
}
vec2 vec2rotate(const vec2& _val, const vec2& _point, float _angle);
namespace etk {
std::ostream& operator <<(std::ostream& _os, const std::vector<vec2 >& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const std::vector<ivec2 >& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const std::vector<uivec2 >& _obj);
//! @previous
std::ostream& operator <<(std::ostream& _os, const std::vector<bvec2 >& _obj);
}