Files
j3ml/src/J3ML/LinearAlgebra/Vector2.cpp

327 lines
7.6 KiB
C++

#include <J3ML/LinearAlgebra/Vector2.h>
#include <cassert>
#include <algorithm>
#include <valarray>
#include <iostream>
namespace J3ML::LinearAlgebra {
Vector2::Vector2(): x(0), y(0)
{}
Vector2::Vector2(float X, float Y): x(X), y(Y)
{}
Vector2::Vector2(const Vector2& rhs): x(rhs.x), y(rhs.y)
{}
float Vector2::operator[](std::size_t index) const
{
return At(index);
}
float &Vector2::operator[](std::size_t index)
{
return At(index);
}
bool Vector2::IsWithinMarginOfError(const Vector2& rhs, float margin) const
{
return this->Distance(rhs) <= margin;
}
bool Vector2::operator==(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector2::operator!=(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector2 Vector2::Min(const Vector2& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y)
};
}
Vector2 Vector2::Max(const Vector2& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y)
};
}
Vector2 Vector2::Clamp(const Vector2& min, const Vector2& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y)
};
}
float Vector2::Distance(const Vector2& to) const
{
return ((*this)-to).Magnitude();
}
float Vector2::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector2::LengthSquared() const
{
return (x*x + y*y);
}
float Vector2::Magnitude() const
{
return std::sqrt(LengthSquared());
}
float Vector2::Dot(const Vector2& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x + a.y * b.y;
}
Vector2 Vector2::Project(const Vector2& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()*rhs.Magnitude());
return rhs * scalar;
}
Vector2 Vector2::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length()
};
else
return {0,0};
}
Vector2 Vector2::Lerp(const Vector2& rhs, float alpha) const
{
return this->operator*(1.0f - alpha) + (rhs * alpha);
}
float Vector2::AngleBetween(const Vector2& rhs) const
{
auto numer = this->Dot(rhs);
auto denom = this->Magnitude() * rhs.Magnitude();
return std::acos(numer / denom);
}
float Vector2::AngleBetween(const Vector2& lhs, const Vector2& rhs)
{ return lhs.AngleBetween(rhs); }
Vector2 Vector2::operator+(const Vector2& rhs) const
{
return {this->x + rhs.x, this->y + rhs.y};
}
Vector2 Vector2::operator-(const Vector2& rhs) const
{
return {this->x - rhs.x, this->y - rhs.y};
}
Vector2 Vector2::operator*(float rhs) const
{
return {
this->x * rhs,
this->y * rhs
};
}
Vector2 Vector2::operator/(float rhs) const
{
return {
this->x / rhs,
this->y / rhs
};
}
Vector2 Vector2::operator-() const
{
return {-x, -y};
}
const Vector2 Vector2::Zero = {0, 0};
const Vector2 Vector2::Up = {0, -1};
const Vector2 Vector2::Down = {0, 1};
const Vector2 Vector2::Left = {-1, 0};
const Vector2 Vector2::Right = {1, 0};
const Vector2 Vector2::NaN = {NAN, NAN};
float Vector2::GetX() const { return x; }
float Vector2::GetY() const { return y; }
float Vector2::LengthSquared(const Vector2 &of) { return of.LengthSquared(); }
Vector2 Vector2::Min(const Vector2 &value, const Vector2 &minimum) { return value.Min(minimum); }
Vector2 Vector2::Max(const Vector2 &value, const Vector2 &maximum) { return value.Max(maximum);}
float Vector2::Length(const Vector2 &of) { return of.Length(); }
void Vector2::SetX(float newX) { x = newX;}
void Vector2::SetY(float newY) { y = newY; }
bool Vector2::IsNormalized(float epsilonSq) const {
return std::abs(LengthSquared() - 1.f) <= epsilonSq;
}
bool Vector2::IsZero(float epsilonSq) const {
return LengthSquared() <= epsilonSq;
}
bool Vector2::IsPerpendicular(const Vector2 &other, float epsilonSq) const {
float dot = Dot(other);
return dot*dot <= epsilonSq * LengthSquared() * other.LengthSquared();
}
Vector2 Vector2::Normalize(const Vector2 &of) { return of.Normalize(); }
Vector2 Vector2::Project(const Vector2 &lhs, const Vector2 &rhs) { return lhs.Project(rhs); }
float Vector2::Dot(const Vector2 &lhs, const Vector2 &rhs) { return lhs.Dot(rhs); }
float Vector2::Magnitude(const Vector2 &of) { return of.Magnitude();}
Vector2 Vector2::Lerp(const Vector2 &lhs, const Vector2 &rhs, float alpha) { return lhs.Lerp(rhs, alpha); }
Vector2 Vector2::Div(const Vector2 &lhs, float rhs) {
return lhs.Div(rhs);
}
Vector2 Vector2::Mul(const Vector2 &lhs, float rhs) {
return lhs.Mul(rhs);
}
Vector2 Vector2::Sub(const Vector2 &lhs, const Vector2 &rhs) {
return lhs.Sub(rhs);
}
Vector2 Vector2::Add(const Vector2 &lhs, const Vector2 &rhs) {
return lhs.Add(rhs);
}
Vector2 Vector2::Add(const Vector2 &rhs) const {
return *this + rhs;
}
Vector2 Vector2::Sub(const Vector2 &rhs) const {
return *this - rhs;
}
Vector2 Vector2::Mul(float scalar) const {
return *this * scalar;
}
Vector2 Vector2::Div(float scalar) const {
return *this / scalar;
}
bool Vector2::IsFinite(const Vector2 &v) {
return v.IsFinite();
}
float Vector2::MinElement() const {
return std::min(x, y);
}
float Vector2::MaxElement() const {
return std::max(x, y);
}
Vector2 Vector2::Mul(const Vector2 &v) const {
return {this->x*v.x, this->y*v.y};
}
bool Vector2::IsFinite() const {
return std::isfinite(x) && std::isfinite(y);
}
Vector2 Vector2::Div(const Vector2 &v) const {
return {this->x/v.x, this->y/v.y};
}
Vector2 Vector2::Abs() const { return {std::abs(x), std::abs(y)};}
float *Vector2::ptr() {
return &x;
}
const float *Vector2::ptr() const { return &x;}
const float Vector2::At(std::size_t index) const {
assert(index >= 0);
assert(index < Dimensions);
return ptr()[index];
}
float &Vector2::At(std::size_t index) {
assert(index >= 0);
assert(index < Dimensions);
return ptr()[index];
}
Vector2 &Vector2::operator/=(float scalar) {
x /= scalar;
y /= scalar;
return *this;
}
Vector2 &Vector2::operator*=(float scalar) {
x *= scalar;
y *= scalar;
return *this;
}
Vector2 &Vector2::operator-=(const Vector2 &rhs) // Subtracts a vector from this vector, in-place
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
Vector2 &Vector2::operator+=(const Vector2 &rhs) // Adds a vector to this vector, in-place.
{
x += rhs.x;
y += rhs.y;
return *this;
}
Vector2 &Vector2::operator=(const Vector2 &rhs) {
x = rhs.x;
y = rhs.y;
return *this;
}
Vector2::Vector2(const float *data) {
assert(data);
x = data[0];
y = data[1];
}
Vector2::Vector2(float scalar) {
x = scalar;
y = scalar;
}
}