130 lines
3.1 KiB
C++
130 lines
3.1 KiB
C++
// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
|
|
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
|
|
|
#pragma once
|
|
|
|
#ifndef _VECTOR2_H
|
|
#define _VECTOR2_H
|
|
|
|
#include "FloatComparison.h"
|
|
#include <math.h>
|
|
|
|
template <typename T>
|
|
struct other_floating_type {};
|
|
template <>
|
|
struct other_floating_type<float> {
|
|
typedef double type;
|
|
};
|
|
template <>
|
|
struct other_floating_type<double> {
|
|
typedef float type;
|
|
};
|
|
|
|
template <typename T>
|
|
class vector2 {
|
|
public:
|
|
T x, y;
|
|
|
|
vector2() :
|
|
x(0.0f),
|
|
y(0.0f) {}
|
|
vector2(T _x, T _y) :
|
|
x(_x),
|
|
y(_y) {}
|
|
explicit vector2(int v) :
|
|
x(T(v)),
|
|
y(T(v)) {}
|
|
explicit vector2(unsigned int v) :
|
|
x(T(v)),
|
|
y(T(v)) {}
|
|
explicit vector2(T v) :
|
|
x(v),
|
|
y(v) {}
|
|
explicit vector2(const T v[2]) :
|
|
x(v[0]),
|
|
y(v[1]) {}
|
|
|
|
// disallow implicit conversion between floating point sizes
|
|
explicit vector2(const vector2<typename other_floating_type<T>::type> &v);
|
|
explicit vector2(const typename other_floating_type<T>::type vals[2]);
|
|
|
|
vector2 operator+(const vector2 &v) const { return vector2(x + v.x, y + v.y); }
|
|
vector2 operator-(const vector2 &v) const { return vector2(x - v.x, y - v.y); }
|
|
vector2 &operator+=(const vector2 &v)
|
|
{
|
|
x += v.x;
|
|
y += v.y;
|
|
return *this;
|
|
}
|
|
vector2 &operator-=(const vector2 &v)
|
|
{
|
|
x -= v.x;
|
|
y -= v.y;
|
|
return *this;
|
|
}
|
|
vector2 &operator*=(const T &a)
|
|
{
|
|
x *= a;
|
|
y *= a;
|
|
return *this;
|
|
}
|
|
vector2 operator-() const { return vector2(-x, -y); }
|
|
|
|
bool operator==(const vector2 &a) const
|
|
{
|
|
return is_equal_exact(a.x, x) && is_equal_exact(a.y, y);
|
|
}
|
|
bool ExactlyEqual(const vector2 &a) const
|
|
{
|
|
return is_equal_exact(a.x, x) && is_equal_exact(a.y, y);
|
|
}
|
|
|
|
friend vector2 operator*(const vector2 &v, const T &a) { return vector2(v.x * a, v.y * a); }
|
|
friend vector2 operator*(const T &a, const vector2 &v) { return v * a; }
|
|
friend vector2 operator*(const vector2 &va, const vector2 &vb) { return vector2(va.x * vb.x, va.y * vb.y); }
|
|
friend vector2 operator/(const vector2 &v, const T &a) { return vector2(v.x / a, v.y / a); }
|
|
friend bool operator<(const vector2 &va, const vector2 &vb) { return va.LengthSqr() < vb.LengthSqr(); }
|
|
|
|
T Length() const { return sqrt(x * x + y * y); }
|
|
T LengthSqr() const { return x * x + y * y; }
|
|
vector2 Normalized() const
|
|
{
|
|
const T invlen = 1.0f / sqrt(x * x + y * y);
|
|
return vector2(x * invlen, y * invlen);
|
|
}
|
|
vector2 NormalizedSafe() const
|
|
{
|
|
const T lenSqr = x * x + y * y;
|
|
if (lenSqr < 1e-18) // sqrt(lenSqr) < 1e-9
|
|
return vector2(1, 0);
|
|
else {
|
|
const T invlen = sqrt(lenSqr);
|
|
return vector2(x / invlen, y / invlen);
|
|
}
|
|
}
|
|
vector2 Rotate(T alpha) // Rotate around center
|
|
{
|
|
return vector2(x * cos(alpha) - y * sin(alpha), y * cos(alpha) + x * sin(alpha));
|
|
}
|
|
|
|
void Print() const { printf("v(%f,%f)\n", x, y); }
|
|
};
|
|
|
|
template <>
|
|
inline vector2<float>::vector2() {}
|
|
template <>
|
|
inline vector2<double>::vector2() {}
|
|
template <>
|
|
inline vector2<float>::vector2(const vector2<double> &v) :
|
|
x(float(v.x)),
|
|
y(float(v.y)) {}
|
|
template <>
|
|
inline vector2<double>::vector2(const vector2<float> &v) :
|
|
x(v.x),
|
|
y(v.y) {}
|
|
|
|
typedef vector2<float> vector2f;
|
|
typedef vector2<double> vector2d;
|
|
|
|
#endif
|