blob: 0b0e8523d2fe0bdfd2311e9544696cd7a0cf7452 [file] [log] [blame]
//#####################################################################
// Copyright 2002-2004, Robert Bridson, Doug Enright, Ronald Fedkiw, Geoffrey Irving, Sergey Koltakov, Igor Neverov, Eran Guendelman, Duc Nguyen.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class VECTOR_2D
//#####################################################################
#ifndef __VECTOR_2D__
#define __VECTOR_2D__
#include <iostream>
#include <assert.h>
#include <math.h>
#include "../Math_Tools/sqr.h"
#include "../Math_Tools/max.h"
#include "../Math_Tools/min.h"
#include "../Read_Write/READ_WRITE_FUNCTIONS.h"
namespace PhysBAM
{
template<class T>
class VECTOR_2D
{
public:
T x, y;
VECTOR_2D()
: x (T()), y (T())
{}
VECTOR_2D (const T x_input, const T y_input)
: x (x_input), y (y_input)
{}
VECTOR_2D (const VECTOR_2D<T>& vector_input)
: x (vector_input.x), y (vector_input.y)
{}
template<class T2> VECTOR_2D (const VECTOR_2D<T2>& vector_input)
: x ( (T) vector_input.x), y ( (T) vector_input.y)
{}
T operator[] (const int i) const
{
assert (1 <= i && i <= 2);
return * ( (const T*) (this) + i - 1);
}
T& operator[] (const int i)
{
assert (1 <= i && i <= 2);
return * ( (T*) (this) + i - 1);
}
bool operator== (const VECTOR_2D<T>& v) const
{
return x == v.x && y == v.y;
}
bool operator!= (const VECTOR_2D<T>& v) const
{
return x != v.x || y != v.y;
}
VECTOR_2D<T> operator-() const
{
return VECTOR_2D<T> (-x, -y);
}
VECTOR_2D<T>& operator+= (const VECTOR_2D<T>& v)
{
x += v.x;
y += v.y;
return *this;
}
VECTOR_2D<T>& operator-= (const VECTOR_2D<T>& v)
{
x -= v.x;
y -= v.y;
return *this;
}
VECTOR_2D<T>& operator*= (const VECTOR_2D<T>& v)
{
x *= v.x;
y *= v.y;
return *this;
}
VECTOR_2D<T>& operator*= (const T a)
{
x *= a;
y *= a;
return *this;
}
VECTOR_2D<T>& operator/= (const T a)
{
assert (a != 0);
T one_over_a = 1 / a;
x *= one_over_a;
y *= one_over_a;
return *this;
}
VECTOR_2D<T>& operator/= (const VECTOR_2D<T>& v)
{
x /= v.x;
y /= v.y;
return *this;
}
VECTOR_2D<T> operator+ (const VECTOR_2D<T>& v) const
{
return VECTOR_2D<T> (x + v.x, y + v.y);
}
VECTOR_2D<T> operator- (const VECTOR_2D<T>& v) const
{
return VECTOR_2D<T> (x - v.x, y - v.y);
}
VECTOR_2D<T> operator* (const VECTOR_2D<T>& v) const
{
return VECTOR_2D<T> (x * v.x, y * v.y);
}
VECTOR_2D<T> operator/ (const VECTOR_2D<T>& v) const
{
return VECTOR_2D<T> (x / v.x, y / v.y);
}
VECTOR_2D<T> operator* (const T a) const
{
return VECTOR_2D<T> (a * x, a * y);
}
VECTOR_2D<T> operator/ (const T a) const
{
assert (a != 0);
T s = 1 / a;
return VECTOR_2D<T> (s * x, s * y);
}
VECTOR_2D<T> fabs() const
{
return VECTOR_2D<T> (fabs (x), fabs (y));
}
T Magnitude_Squared() const
{
return sqr (x) + sqr (y);
}
T Magnitude() const
{
return sqrt (sqr (x) + sqr (y));
}
T Normalize()
{
T magnitude = Magnitude();
assert (magnitude != 0);
T s = 1 / magnitude;
x *= s;
y *= s;
return magnitude;
}
T Robust_Normalize (T tolerance = (T) 1e-8, const VECTOR_2D<T>& fallback = VECTOR_2D<T> (1, 0))
{
T magnitude = Magnitude();
if (magnitude > tolerance)
{
T s = 1 / magnitude;
x *= s;
y *= s;
}
else
{
*this = fallback;
}
return magnitude;
}
VECTOR_2D<T> Normalized() const
{
T magnitude = Magnitude();
assert (magnitude != 0);
T s = 1 / magnitude;
return VECTOR_2D<T> (x * s, y * s);
}
VECTOR_2D<T> Robust_Normalized (T tolerance = (T) 1e-8, const VECTOR_2D<T>& fallback = VECTOR_2D<T> (1, 0))
{
T magnitude = Magnitude();
if (magnitude > tolerance) return *this / magnitude;
else return fallback;
}
VECTOR_2D<T> Rotate_Clockwise_90() const
{
return VECTOR_2D<T> (y, -x);
}
VECTOR_2D<T> Rotate_Counterclockwise_90() const
{
return VECTOR_2D<T> (-y, x);
}
VECTOR_2D<T> Rotate_Counterclockwise_Multiple_90 (const int n) const
{
VECTOR_2D<T> r (*this);
if (n & 2) r = -r;
return n & 1 ? r.Rotate_Counterclockwise_90() : r;
}
T Min_Element() const
{
return min (x, y);
}
T Max_Element() const
{
return max (x, y);
}
T Max_Abs_Element() const
{
return maxabs (x, y);
}
int Dominant_Axis() const
{
return (::fabs (x) > ::fabs (y)) ? 1 : 2;
}
static T Dot_Product (const VECTOR_2D<T>& v1, const VECTOR_2D<T>& v2)
{
return v1.x * v2.x + v1.y * v2.y;
}
VECTOR_2D<T> Projected_On_Unit_Direction (const VECTOR_2D<T>& direction) const
{
return Dot_Product (*this, direction) * direction;
}
VECTOR_2D<T> Projected (const VECTOR_2D<T>& direction) const // un-normalized direction
{
return Dot_Product (*this, direction) / Dot_Product (direction, direction) * direction;
}
void Project_On_Unit_Direction (const VECTOR_2D<T>& direction)
{
*this = Dot_Product (*this, direction) * direction;
}
void Project (const VECTOR_2D<T>& direction) // un-normalized direction
{
*this = Dot_Product (*this, direction) / Dot_Product (direction, direction) * direction;
}
VECTOR_2D<T> Projected_Orthogonal_To_Unit_Direction (const VECTOR_2D<T>& direction) const
{
T dot_product = Dot_Product (*this, direction);
return VECTOR_2D<T> (x - dot_product * direction.x, y - dot_product * direction.y);
}
static T Cross_Product (const VECTOR_2D<T>& v1, const VECTOR_2D<T>& v2)
{
return v1.x * v2.y - v2.x * v1.y;
}
static T Angle_Between (const VECTOR_2D<T>& v1, const VECTOR_2D<T>& v2)
{
return acos (max ( (T) - 1, min ( (T) 1, Dot_Product (v1, v2) / (v1.Magnitude() * v2.Magnitude()))));
}
void Print() const
{
std::cout << "VECTOR_2D<T>: " << x << "," << y << std::endl;
}
template<class RW>
void Read (std::istream &input_stream)
{
Read_Binary<RW> (input_stream, x, y);
}
template<class RW>
void Write (std::ostream &output_stream) const
{
Write_Binary<RW> (output_stream, x, y);
}
//#####################################################################
};
template<>
inline VECTOR_2D<int> VECTOR_2D<int>::operator/ (const int a) const
{
return VECTOR_2D<int> (x / a, y / a);
}
template<>
inline VECTOR_2D<int>& VECTOR_2D<int>::operator/= (const int a)
{
x /= a;
y /= a;
return *this;
}
template<class T>
inline VECTOR_2D<T> operator* (const T a, const VECTOR_2D<T>& v)
{
return VECTOR_2D<T> (a * v.x, a * v.y);
}
template<class T>
inline std::istream& operator>> (std::istream& input_stream, VECTOR_2D<T>& v)
{
input_stream >> v.x >> v.y;
return input_stream;
}
template<class T>
inline std::ostream& operator<< (std::ostream& output_stream, const VECTOR_2D<T>& v)
{
output_stream << v.x << " " << v.y;
return output_stream;
}
}
#endif