359 lines
10 KiB
C++
359 lines
10 KiB
C++
/***************************************************************************
|
|
* Vec2.h *
|
|
* *
|
|
* Basic operations on 2-dimensional vectors. This special case is useful *
|
|
* because nearly all operations are performed inline. *
|
|
* *
|
|
* HISTORY *
|
|
* Name Date Description *
|
|
* *
|
|
* arvo 05/22/98 Added TimedVec2, extending Vec2. *
|
|
* arvo 06/17/93 Initial coding. *
|
|
* *
|
|
*--------------------------------------------------------------------------*
|
|
* Copyright (C) 1999, James Arvo *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify it *
|
|
* under the terms of the GNU General Public License as published by the *
|
|
* Free Software Foundation. See http://www.fsf.org/copyleft/gpl.html *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, but *
|
|
* WITHOUT EXPRESS OR IMPLIED WARRANTY of merchantability or fitness for *
|
|
* any particular purpose. See the GNU General Public License for more *
|
|
* details. *
|
|
* *
|
|
***************************************************************************/
|
|
#ifndef __VEC2_INCLUDED__
|
|
#define __VEC2_INCLUDED__
|
|
|
|
#include <math.h>
|
|
#include <iostream>
|
|
#include "ArvoMath.h"
|
|
|
|
namespace ArvoMath {
|
|
|
|
class Vec2; // 2-D floating-point vector.
|
|
class TimedVec2; // 2-D vector with a time stamp.
|
|
class Mat2x2; // 2x2 floating-point matrix.
|
|
|
|
class Vec2 {
|
|
public:
|
|
Vec2( ) { x = 0.0; y = 0.0; }
|
|
Vec2( float a, float b ) { x = a; y = b; }
|
|
Vec2( const Vec2 &A ) { x = A.X(); y = A.Y(); }
|
|
~Vec2() {}
|
|
Vec2 &operator=( float s ) { return Set( s, s ); }
|
|
Vec2 &operator=( const Vec2 &A ) { return Set( A.X(), A.Y() ); }
|
|
float X() const { return x; }
|
|
float Y() const { return y; }
|
|
float &X() { return x; }
|
|
float &Y() { return y; }
|
|
float operator[]( int i ) const { return *( &x + i ); }
|
|
float &operator[]( int i ) { return *( &x + i ); }
|
|
Vec2 &Set( float a, float b ) { x = a; y = b; return *this; }
|
|
Vec2 &Set( const Vec2 &A ) { return Set( A.X(), A.Y() ); }
|
|
public:
|
|
static const Vec2 Zero;
|
|
static const Vec2 Xaxis;
|
|
static const Vec2 Yaxis;
|
|
protected:
|
|
float x, y;
|
|
};
|
|
|
|
// This class simply adds a time field to the Vec2 class so that time-stamped
|
|
// coordinates can be easily inserted into objects such as Polylines.
|
|
|
|
class TimedVec2 : public Vec2 {
|
|
public:
|
|
TimedVec2() { time = 0; }
|
|
TimedVec2( const Vec2 &p , long u = 0 ) { Set( p ); time = u; }
|
|
TimedVec2( float x, float y, long u = 0 ) { Set(x,y); time = u; }
|
|
~TimedVec2() {}
|
|
Vec2 &Coord() { return *this; }
|
|
Vec2 Coord() const { return *this; }
|
|
long Time () const { return time; }
|
|
void SetTime( long u ) { time = u; }
|
|
protected:
|
|
long time;
|
|
};
|
|
|
|
class Mat2x2 {
|
|
public:
|
|
Mat2x2( ) { Set( 0, 0, 0, 0 ); }
|
|
Mat2x2( float a, float b, float c, float d ) { Set( a, b, c, d ); }
|
|
Mat2x2( const Vec2 &c1, const Vec2 &c2 );
|
|
~Mat2x2( ) {}
|
|
Mat2x2 &operator*=( float scale );
|
|
Mat2x2 operator* ( float scale ) const;
|
|
void Set( float a, float b, float c, float d )
|
|
{ m[0][0] = a; m[0][1] = b; m[1][0] = c; m[1][1] = d; }
|
|
float operator()( int i, int j ) const { return m[i][j]; }
|
|
float &operator()( int i, int j ) { return m[i][j]; }
|
|
private:
|
|
float m[2][2];
|
|
};
|
|
|
|
|
|
//==========================================
|
|
//=== Miscellaneous external functions ===
|
|
//==========================================
|
|
|
|
extern float Normalize( Vec2 &A );
|
|
extern Vec2 Min ( const Vec2 &A, const Vec2 &B );
|
|
extern Vec2 Max ( const Vec2 &A, const Vec2 &B );
|
|
|
|
|
|
//==========================================
|
|
//=== Norm-related functions ===
|
|
//==========================================
|
|
|
|
inline double LenSqr ( const Vec2 &A ) { return Sqr(A[0]) + Sqr(A[1]); }
|
|
inline double Len ( const Vec2 &A ) { return sqrt( LenSqr( A ) ); }
|
|
inline double OneNorm( const Vec2 &A ) { return Abs( A.X() ) + Abs( A.Y() ); }
|
|
inline double TwoNorm( const Vec2 &A ) { return Len(A); }
|
|
inline float SupNorm( const Vec2 &A ) { return MaxAbs( A.X(), A.Y() ); }
|
|
|
|
|
|
//==========================================
|
|
//=== Addition ===
|
|
//==========================================
|
|
|
|
inline Vec2 operator+( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return Vec2( A.X() + B.X(), A.Y() + B.Y() );
|
|
}
|
|
|
|
inline Vec2& operator+=( Vec2 &A, const Vec2 &B )
|
|
{
|
|
A.X() += B.X();
|
|
A.Y() += B.Y();
|
|
return A;
|
|
}
|
|
|
|
|
|
//==========================================
|
|
//=== Subtraction ===
|
|
//==========================================
|
|
|
|
inline Vec2 operator-( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return Vec2( A.X() - B.X(), A.Y() - B.Y() );
|
|
}
|
|
|
|
inline Vec2 operator-( const Vec2 &A )
|
|
{
|
|
return Vec2( -A.X(), -A.Y() );
|
|
}
|
|
|
|
inline Vec2& operator-=( Vec2 &A, const Vec2 &B )
|
|
{
|
|
A.X() -= B.X();
|
|
A.Y() -= B.Y();
|
|
return A;
|
|
}
|
|
|
|
|
|
//==========================================
|
|
//=== Multiplication ===
|
|
//==========================================
|
|
|
|
inline Vec2 operator*( float c, const Vec2 &A )
|
|
{
|
|
return Vec2( c * A.X(), c * A.Y() );
|
|
}
|
|
|
|
inline Vec2 operator*( const Vec2 &A, float c )
|
|
{
|
|
return Vec2( c * A.X(), c * A.Y() );
|
|
}
|
|
|
|
inline float operator*( const Vec2 &A, const Vec2 &B ) // Inner product
|
|
{
|
|
return A.X() * B.X() + A.Y() * B.Y();
|
|
}
|
|
|
|
inline Vec2& operator*=( Vec2 &A, float c )
|
|
{
|
|
A.X() *= c;
|
|
A.Y() *= c;
|
|
return A;
|
|
}
|
|
|
|
//==========================================
|
|
//=== Division ===
|
|
//==========================================
|
|
|
|
inline Vec2 operator/( const Vec2 &A, float c )
|
|
{
|
|
return Vec2( A.X() / c, A.Y() / c );
|
|
}
|
|
|
|
inline Vec2 operator/( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A - B * (( A * B ) / LenSqr( B ));
|
|
}
|
|
|
|
|
|
//==========================================
|
|
//=== Comparison ===
|
|
//==========================================
|
|
|
|
inline int operator==( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() == B.X() && A.Y() == B.Y();
|
|
}
|
|
|
|
inline int operator!=( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() != B.X() || A.Y() != B.Y();
|
|
}
|
|
|
|
inline int operator<=( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() <= B.X() && A.Y() <= B.Y();
|
|
}
|
|
|
|
inline int operator<( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() < B.X() && A.Y() < B.Y();
|
|
}
|
|
|
|
inline int operator>=( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() >= B.X() && A.Y() >= B.Y();
|
|
}
|
|
|
|
inline int operator>( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() > B.X() && A.Y() > B.Y();
|
|
}
|
|
|
|
//==========================================
|
|
//=== Miscellaneous ===
|
|
//==========================================
|
|
|
|
inline float operator|( const Vec2 &A, const Vec2 &B ) // Inner product
|
|
{
|
|
return A * B;
|
|
}
|
|
|
|
inline Vec2 Unit( const Vec2 &A )
|
|
{
|
|
float c = LenSqr( A );
|
|
if( c > 0.0 ) c = 1.0 / sqrt( c );
|
|
return c * A;
|
|
}
|
|
|
|
inline Vec2 Unit( const Vec2 &A, float &len )
|
|
{
|
|
float c = LenSqr( A );
|
|
if( c > 0.0 )
|
|
{
|
|
len = sqrt( c );
|
|
return A / len;
|
|
}
|
|
len = 0.0;
|
|
return A;
|
|
}
|
|
|
|
inline Vec2 Unit( float x, float y )
|
|
{
|
|
return Unit( Vec2( x, y ) );
|
|
}
|
|
|
|
inline double dist( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return Len( A - B );
|
|
}
|
|
|
|
inline float operator^( const Vec2 &A, const Vec2 &B )
|
|
{
|
|
return A.X() * B.Y() - A.Y() * B.X();
|
|
}
|
|
|
|
inline int Quadrant( const Vec2 &A )
|
|
{
|
|
if( A.Y() >= 0.0 ) return A.X() >= 0.0 ? 1 : 2;
|
|
return A.X() >= 0.0 ? 4 : 3;
|
|
}
|
|
|
|
inline Vec2 OrthogonalTo( const Vec2 &A ) // A vector orthogonal to that given.
|
|
{
|
|
return Vec2( -A.Y(), A.X() );
|
|
}
|
|
|
|
inline Vec2 Interpolate( const Vec2 &A, const Vec2 &B, float t )
|
|
{
|
|
// Compute a point along the segment joining points A and B
|
|
// according to the normalized parameter t in [0,1].
|
|
return ( 1.0 - t ) * A + t * B;
|
|
}
|
|
|
|
//==========================================
|
|
//=== Operations involving Matrices ===
|
|
//==========================================
|
|
|
|
inline Mat2x2 Outer( const Vec2 &A, const Vec2 &B ) // Outer product.
|
|
{
|
|
Mat2x2 C;
|
|
C(0,0) = A.X() * B.X();
|
|
C(0,1) = A.X() * B.Y();
|
|
C(1,0) = A.Y() * B.X();
|
|
C(1,1) = A.Y() * B.Y();
|
|
return C;
|
|
}
|
|
|
|
inline Vec2 operator*( const Mat2x2 &M, const Vec2 &A )
|
|
{
|
|
return Vec2(
|
|
M(0,0) * A.X() + M(0,1) * A.Y(),
|
|
M(1,0) * A.X() + M(1,1) * A.Y()
|
|
);
|
|
}
|
|
|
|
inline Mat2x2 &Mat2x2::operator*=( float scale )
|
|
{
|
|
m[0][0] *= scale;
|
|
m[0][1] *= scale;
|
|
m[1][0] *= scale;
|
|
m[1][1] *= scale;
|
|
return *this;
|
|
}
|
|
|
|
inline Mat2x2 Mat2x2::operator*( float scale ) const
|
|
{
|
|
return Mat2x2(
|
|
scale * m[0][0], scale * m[0][1],
|
|
scale * m[1][0], scale * m[1][1]
|
|
);
|
|
}
|
|
|
|
inline Mat2x2 operator*( float scale, const Mat2x2 &M )
|
|
{
|
|
return M * scale;
|
|
}
|
|
|
|
inline float Norm1( const Mat2x2 &A )
|
|
{
|
|
return Max( Abs(A(0,0)) + Abs(A(0,1)), Abs(A(1,0)) + Abs(A(1,1)) );
|
|
}
|
|
|
|
inline double det( const Mat2x2 &A )
|
|
{
|
|
return A(0,0) * A(1,1) - A(1,0) * A(0,1);
|
|
}
|
|
|
|
extern Vec2 Solve( // Return solution x of the system Ax = b.
|
|
const Mat2x2 &A,
|
|
const Vec2 &b
|
|
);
|
|
|
|
//==========================================
|
|
//=== Output routines ===
|
|
//==========================================
|
|
|
|
extern std::ostream &operator<<( std::ostream &out, const Vec2 & );
|
|
extern std::ostream &operator<<( std::ostream &out, const Mat2x2 & );
|
|
};
|
|
#endif
|