123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981 |
- /*
- *
- * Mathematics Subpackage (VrMath)
- *
- *
- * Author: Samuel R. Buss, [email protected].
- * Web page: http://math.ucsd.edu/~sbuss/MathCG
- *
- *
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- *
- *
- */
- //
- // Linear Algebra Classes over R2
- //
- //
- // A. Vector and Position classes
- //
- // A.1. VectorR2: a column vector of length 2
- //
- // A.2. VectorHgR2 - homogenous vector for R2 (a 3-Vector)
- //
- // B. Matrix Classes
- //
- // B.1 LinearMapR2 - arbitrary linear map; 2x2 real matrix
- //
- // B.2 RotationMapR2 - orthonormal 2x2 matrix
- //
- #ifndef LINEAR_R2_H
- #define LINEAR_R2_H
- #include <math.h>
- #include <assert.h>
- #include <iostream>
- #include "MathMisc.h"
- using namespace std;
- class VectorR2; // R2 Vector
- class VectorHgR2;
- class Matrix2x2;
- class LinearMapR2; // 2x2 real matrix
- class AffineMapR3; // Affine Map (3x4 Matrix)
- class RotationMapR2; // 2x2 rotation map
- // **************************************
- // VectorR2 class *
- // * * * * * * * * * * * * * * * * * * **
- class VectorR2 {
- public:
- double x, y; // The x & y coordinates.
- public:
- VectorR2( ) : x(0.0), y(0.0) {}
- VectorR2( double xVal, double yVal )
- : x(xVal), y(yVal) {}
- VectorR2( const VectorHgR2& uH );
- VectorR2& SetZero() { x=0.0; y=0.0; return *this;}
- VectorR2& Set( double xx, double yy )
- { x=xx; y=yy; return *this;}
- VectorR2& Load( const double* v );
- VectorR2& Load( const float* v );
- void Dump( double* v ) const;
- void Dump( float* v ) const;
- static const VectorR2 Zero;
- static const VectorR2 UnitX;
- static const VectorR2 UnitY;
- static const VectorR2 NegUnitX;
- static const VectorR2 NegUnitY;
- VectorR2& operator+= ( const VectorR2& v )
- { x+=v.x; y+=v.y; return(*this); }
- VectorR2& operator-= ( const VectorR2& v )
- { x-=v.x; y-=v.y; return(*this); }
- VectorR2& operator*= ( double m )
- { x*=m; y*=m; return(*this); }
- VectorR2& operator/= ( double m )
- { register double mInv = 1.0/m;
- x*=mInv; y*=mInv;
- return(*this); }
- VectorR2 operator- () const { return ( VectorR2(-x, -y) ); }
- VectorR2& ArrayProd(const VectorR2&); // Component-wise product
- VectorR2& AddScaled( const VectorR2& u, double s );
- double Norm() const { return ( sqrt( x*x + y*y ) ); }
- double L1Norm() const { return (Max(fabs(x),fabs(y))); }
- double Dist( const VectorR2& u ) const; // Distance from u
- double DistSq( const VectorR2& u ) const; // Distance from u
- double NormSq() const { return ( x*x + y*y ); }
- double MaxAbs() const;
- VectorR2& Normalize () { *this /= Norm(); return *this;} // No error checking
- VectorR2& MakeUnit(); // Normalize() with error checking
- VectorR2& ReNormalize();
- bool IsUnit( double tolerance = 1.0e-15 ) const
- { register double norm = Norm();
- return ( 1.0+tolerance>=norm && norm>=1.0-tolerance ); }
- bool IsZero() const { return ( x==0.0 && y==0.0 ); }
- bool NearZero(double tolerance) const { return( MaxAbs()<=tolerance );}
- // tolerance should be non-negative
- VectorR2& Rotate( double theta ); // rotate through angle theta
- VectorR2& Rotate( double costheta, double sintheta );
- };
- inline VectorR2 operator+( const VectorR2& u, const VectorR2& v );
- inline VectorR2 operator-( const VectorR2& u, const VectorR2& v );
- inline VectorR2 operator*( const VectorR2& u, double m);
- inline VectorR2 operator*( double m, const VectorR2& u);
- inline VectorR2 operator/( const VectorR2& u, double m);
- inline int operator==( const VectorR2& u, const VectorR2& v );
- inline double operator^ (const VectorR2& u, const VectorR2& v ); // Dot Product
- inline VectorR2 ArrayProd ( const VectorR2& u, const VectorR2& v );
- inline double Mag(const VectorR2& u) { return u.Norm(); }
- inline double Dist(const VectorR2& u, const VectorR2& v) { return u.Dist(v); }
- inline double DistSq(const VectorR2& u, const VectorR2& v) { return u.DistSq(v); }
- inline double NormalizeError (const VectorR2&);
- // ****************************************
- // VectorHgR2 class *
- // * * * * * * * * * * * * * * * * * * * **
- class VectorHgR2 {
- public:
- double x, y, w; // The x & y & w coordinates.
- public:
- VectorHgR2( ) : x(0.0), y(0.0), w(1.0) {}
- VectorHgR2( double xVal, double yVal )
- : x(xVal), y(yVal), w(1.0) {}
- VectorHgR2( double xVal, double yVal, double wVal )
- : x(xVal), y(yVal), w(wVal) {}
- VectorHgR2 ( const VectorR2& u ) : x(u.x), y(u.y), w(1.0) {}
- };
- // ********************************************************************
- // Matrix2x2 - base class for 2x2 matrices *
- // * * * * * * * * * * * * * * * * * * * * * **************************
- class Matrix2x2 {
- public:
- double m11, m12, m21, m22;
-
- // Implements a 2x2 matrix: m_i_j - row-i and column-j entry
- static const Matrix2x2 Identity;
- public:
- inline Matrix2x2();
- inline Matrix2x2( const VectorR2&, const VectorR2& ); // Sets by columns!
- inline Matrix2x2( double, double, double, double ); // Sets by columns
- inline void SetIdentity (); // Set to the identity map
- inline void SetZero (); // Set to the zero map
- inline void Set( const VectorR2&, const VectorR2& );
- inline void Set( double, double, double, double );
- inline void SetByRows( const VectorR2&, const VectorR2& );
- inline void SetByRows( double, double, double, double );
- inline void SetColumn1 ( double, double );
- inline void SetColumn2 ( double, double );
- inline void SetColumn1 ( const VectorR2& );
- inline void SetColumn2 ( const VectorR2& );
- inline VectorR2 Column1() const;
- inline VectorR2 Column2() const;
- inline void SetRow1 ( double, double );
- inline void SetRow2 ( double, double );
- inline void SetRow1 ( const VectorR2& );
- inline void SetRow2 ( const VectorR2& );
- inline VectorR2 Row1() const;
- inline VectorR2 Row2() const;
- inline void SetDiagonal( double, double );
- inline void SetDiagonal( const VectorR2& );
- inline double Diagonal( int );
- inline void MakeTranspose(); // Transposes it.
- inline void operator*= (const Matrix2x2& B); // Matrix product
- inline Matrix2x2& ReNormalize();
- inline void Transform( VectorR2* ) const;
- inline void Transform( const VectorR2& src, VectorR2* dest) const;
- };
- inline double NormalizeError( const Matrix2x2& );
- inline VectorR2 operator* ( const Matrix2x2&, const VectorR2& );
- ostream& operator<< ( ostream& os, const Matrix2x2& A );
- // *****************************************
- // LinearMapR2 class *
- // * * * * * * * * * * * * * * * * * * * * *
- class LinearMapR2 : public Matrix2x2 {
- public:
- LinearMapR2();
- LinearMapR2( const VectorR2&, const VectorR2& ); // Sets by columns!
- LinearMapR2( double, double, double, double ); // Sets by columns
- LinearMapR2 ( const Matrix2x2& );
- inline void Negate();
- inline LinearMapR2& operator+= (const Matrix2x2& );
- inline LinearMapR2& operator-= (const Matrix2x2& );
- inline LinearMapR2& operator*= (double);
- inline LinearMapR2& operator/= (double);
- inline LinearMapR2& operator*= (const Matrix2x2& ); // Matrix product
- inline LinearMapR2 Transpose() const;
- inline double Determinant () const; // Returns the determinant
- LinearMapR2 Inverse() const; // Returns inverse
- LinearMapR2& Invert(); // Converts into inverse.
- VectorR2 Solve(const VectorR2&) const; // Returns solution
- LinearMapR2 PseudoInverse() const; // Returns pseudo-inverse TO DO
- VectorR2 PseudoSolve(const VectorR2&); // Finds least squares solution TO DO
- };
-
- inline LinearMapR2 operator+ ( const LinearMapR2&, const LinearMapR2&);
- inline LinearMapR2 operator- ( const Matrix2x2& );
- inline LinearMapR2 operator- ( const LinearMapR2&, const LinearMapR2&);
- inline LinearMapR2 operator* ( const LinearMapR2&, double);
- inline LinearMapR2 operator* ( double, const LinearMapR2& );
- inline LinearMapR2 operator/ ( const LinearMapR2&, double );
- inline LinearMapR2 operator* ( const Matrix2x2&, const LinearMapR2& );
- inline LinearMapR2 operator* ( const LinearMapR2&, const Matrix2x2& );
- inline LinearMapR2 operator* ( const LinearMapR2&, const LinearMapR2& );
- // Matrix product (composition)
- // *******************************************
- // RotationMapR2class *
- // * * * * * * * * * * * * * * * * * * * * * *
- class RotationMapR2 : public Matrix2x2 {
- public:
- RotationMapR2();
- RotationMapR2( const VectorR2&, const VectorR2& ); // Sets by columns!
- RotationMapR2( double, double, double, double ); // Sets by columns!
- RotationMapR2& SetZero(); // IT IS AN ERROR TO USE THIS FUNCTION!
- inline RotationMapR2& operator*= (const RotationMapR2& ); // Matrix product
- inline RotationMapR2 Transpose() const;
- inline RotationMapR2 Inverse() const { return Transpose(); }; // Returns the transpose
- inline RotationMapR2& Invert() { MakeTranspose(); return *this; }; // Transposes it.
- inline VectorR2 Invert(const VectorR2&) const; // Returns solution
- };
-
- inline RotationMapR2 operator* ( const RotationMapR2&, const RotationMapR2& );
- // Matrix product (composition)
- // ***************************************************************
- // * 2-space vector and matrix utilities (prototypes) *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Returns the angle between vectors u and v.
- // Use AngleUnit if both vectors are unit vectors
- inline double Angle( const VectorR2& u, const VectorR2& v);
- inline double AngleUnit( const VectorR2& u, const VectorR2& v );
- // Returns a righthanded orthonormal basis to complement vector u
- // The vector u must be unit.
- inline VectorR2 GetOrtho( const VectorR2& u );
- // Projections
- inline VectorR2 ProjectToUnit ( const VectorR2& u, const VectorR2& v);
- // Project u onto v
- inline VectorR2 ProjectPerpUnit ( const VectorR2& u, const VectorR2 & v);
- // Project perp to v
- // v must be a unit vector.
- // Projection maps (LinearMapR2's)
- inline LinearMapR2 VectorProjectMap( const VectorR2& u );
- inline LinearMapR2 PerpProjectMap ( const VectorR2& u );
- // u - must be unit vector.
- // Rotation Maps
- inline RotationMapR2 RotateToMap( const VectorR2& fromVec, const VectorR2& toVec);
- // fromVec and toVec should be unit vectors
- // ***************************************************************
- // * Stream Output Routines (Prototypes) *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ostream& operator<< ( ostream& os, const VectorR2& u );
- // *****************************************************
- // * VectorR2 class - inlined functions *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * *
- inline VectorR2& VectorR2::Load( const double* v )
- {
- x = *v;
- y = *(v+1);
- return *this;
- }
- inline VectorR2& VectorR2::Load( const float* v )
- {
- x = *v;
- y = *(v+1);
- return *this;
- }
- inline void VectorR2::Dump( double* v ) const
- {
- *v = x;
- *(v+1) = y;
- }
- inline void VectorR2::Dump( float* v ) const
- {
- *v = (float)x;
- *(v+1) = (float)y;
- }
- inline VectorR2& VectorR2::ArrayProd (const VectorR2& v) // Component-wise Product
- {
- x *= v.x;
- y *= v.y;
- return ( *this );
- }
- inline VectorR2& VectorR2::MakeUnit () // Convert to unit vector (or leave zero).
- {
- double nSq = NormSq();
- if (nSq != 0.0) {
- *this /= sqrt(nSq);
- }
- return *this;
- }
- inline VectorR2& VectorR2::ReNormalize() // Convert near unit back to unit
- {
- double nSq = NormSq();
- register double mFact = 1.0-0.5*(nSq-1.0); // Multiplicative factor
- *this *= mFact;
- return *this;
- }
- // Rotate through angle theta
- inline VectorR2& VectorR2::Rotate( double theta )
- {
- double costheta = cos(theta);
- double sintheta = sin(theta);
- double tempx = x*costheta - y*sintheta;
- y = y*costheta + x*sintheta;
- x = tempx;
- return *this;
- }
- inline VectorR2& VectorR2::Rotate( double costheta, double sintheta )
- {
- double tempx = x*costheta + y*sintheta;
- y = y*costheta - x*sintheta;
- x = tempx;
- return *this;
- }
- inline double VectorR2::MaxAbs() const
- {
- register double m;
- m = (x>=0.0) ? x : -x;
- if ( y>m ) m=y;
- else if ( -y >m ) m = -y;
- return m;
- }
- inline VectorR2 operator+( const VectorR2& u, const VectorR2& v )
- {
- return VectorR2(u.x+v.x, u.y+v.y );
- }
- inline VectorR2 operator-( const VectorR2& u, const VectorR2& v )
- {
- return VectorR2(u.x-v.x, u.y-v.y );
- }
- inline VectorR2 operator*( const VectorR2& u, register double m)
- {
- return VectorR2( u.x*m, u.y*m );
- }
- inline VectorR2 operator*( register double m, const VectorR2& u)
- {
- return VectorR2( u.x*m, u.y*m );
- }
- inline VectorR2 operator/( const VectorR2& u, double m)
- {
- register double mInv = 1.0/m;
- return VectorR2( u.x*mInv, u.y*mInv );
- }
- inline int operator==( const VectorR2& u, const VectorR2& v )
- {
- return ( u.x==v.x && u.y==v.y );
- }
- inline double operator^ ( const VectorR2& u, const VectorR2& v ) // Dot Product
- {
- return ( u.x*v.x + u.y*v.y );
- }
- inline VectorR2 ArrayProd ( const VectorR2& u, const VectorR2& v )
- {
- return ( VectorR2( u.x*v.x, u.y*v.y ) );
- }
- inline VectorR2& VectorR2::AddScaled( const VectorR2& u, double s )
- {
- x += s*u.x;
- y += s*u.y;
- return(*this);
- }
- inline VectorR2::VectorR2( const VectorHgR2& uH )
- : x(uH.x), y(uH.y)
- {
- *this /= uH.w;
- }
- inline double NormalizeError (const VectorR2& u)
- {
- register double discrepancy;
- discrepancy = u.x*u.x + u.y*u.y - 1.0;
- if ( discrepancy < 0.0 ) {
- discrepancy = -discrepancy;
- }
- return discrepancy;
- }
- inline double VectorR2::Dist( const VectorR2& u ) const // Distance from u
- {
- return sqrt( DistSq(u) );
- }
- inline double VectorR2::DistSq( const VectorR2& u ) const // Distance from u
- {
- return ( (x-u.x)*(x-u.x) + (y-u.y)*(y-u.y) );
- }
- // *********************************************************
- // * Matrix2x2 class - inlined functions *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * *****
- inline Matrix2x2::Matrix2x2() {}
- inline Matrix2x2::Matrix2x2( const VectorR2& u, const VectorR2& v )
- {
- m11 = u.x; // Column 1
- m21 = u.y;
- m12 = v.x; // Column 2
- m22 = v.y;
- }
- inline Matrix2x2::Matrix2x2( double a11, double a21, double a12, double a22 )
- // Values specified in column order!!!
- {
- m11 = a11; // Row 1
- m12 = a12;
- m21 = a21; // Row 2
- m22 = a22;
- }
- inline void Matrix2x2::SetIdentity ( )
- {
- m11 = m22 = 1.0;
- m12 = m21 = 0.0;
- }
- inline void Matrix2x2::Set( const VectorR2& u, const VectorR2& v )
- {
- m11 = u.x; // Column 1
- m21 = u.y;
- m12 = v.x; // Column 2
- m22 = v.y;
- }
- inline void Matrix2x2::Set( double a11, double a21, double a12, double a22 )
- // Values specified in column order!!!
- {
- m11 = a11; // Row 1
- m12 = a12;
- m21 = a21; // Row 2
- m22 = a22;
- }
- inline void Matrix2x2::SetZero( )
- {
- m11 = m12 = m21 = m22 = 0.0;
- }
- inline void Matrix2x2::SetByRows( const VectorR2& u, const VectorR2& v )
- {
- m11 = u.x; // Row 1
- m12 = u.y;
- m21 = v.x; // Row 2
- m22 = v.y;
- }
- inline void Matrix2x2::SetByRows( double a11, double a12, double a21, double a22 )
- // Values specified in row order!!!
- {
- m11 = a11; // Row 1
- m12 = a12;
- m21 = a21; // Row 2
- m22 = a22;
- }
- inline void Matrix2x2::SetColumn1 ( double x, double y )
- {
- m11 = x; m21 = y;
- }
- inline void Matrix2x2::SetColumn2 ( double x, double y )
- {
- m12 = x; m22 = y;
- }
- inline void Matrix2x2::SetColumn1 ( const VectorR2& u )
- {
- m11 = u.x; m21 = u.y;
- }
- inline void Matrix2x2::SetColumn2 ( const VectorR2& u )
- {
- m12 = u.x; m22 = u.y;
- }
- VectorR2 Matrix2x2::Column1() const
- {
- return ( VectorR2(m11, m21) );
- }
- VectorR2 Matrix2x2::Column2() const
- {
- return ( VectorR2(m12, m22) );
- }
- inline void Matrix2x2::SetRow1 ( double x, double y )
- {
- m11 = x; m12 = y;
- }
- inline void Matrix2x2::SetRow2 ( double x, double y )
- {
- m21 = x; m22 = y;
- }
- inline void Matrix2x2::SetRow1 ( const VectorR2& u )
- {
- m11 = u.x; m12 = u.y;
- }
- inline void Matrix2x2::SetRow2 ( const VectorR2& u )
- {
- m21 = u.x; m22 = u.y;
- }
- VectorR2 Matrix2x2::Row1() const
- {
- return ( VectorR2(m11, m12) );
- }
- VectorR2 Matrix2x2::Row2() const
- {
- return ( VectorR2(m21, m22) );
- }
- inline void Matrix2x2::SetDiagonal( double x, double y )
- {
- m11 = x;
- m22 = y;
- }
- inline void Matrix2x2::SetDiagonal( const VectorR2& u )
- {
- SetDiagonal ( u.x, u.y );
- }
- inline double Matrix2x2::Diagonal( int i )
- {
- switch (i) {
- case 0:
- return m11;
- case 1:
- return m22;
- default:
- assert(0);
- return 0.0;
- }
- }
- inline void Matrix2x2::MakeTranspose() // Transposes it.
- {
- register double temp;
- temp = m12;
- m12 = m21;
- m21=temp;
- }
- inline void Matrix2x2::operator*= (const Matrix2x2& B) // Matrix product
- {
- double t1; // temporary value
- t1 = m11*B.m11 + m12*B.m21;
- m12 = m11*B.m12 + m12*B.m22;
- m11 = t1;
- t1 = m21*B.m11 + m22*B.m21;
- m22 = m21*B.m12 + m22*B.m22;
- m21 = t1;
- }
- inline Matrix2x2& Matrix2x2::ReNormalize() // Re-normalizes nearly orthonormal matrix
- {
- register double alpha = m11*m11+m21*m21; // First column's norm squared
- register double beta = m12*m12+m22*m22; // Second column's norm squared
- alpha = 1.0 - 0.5*(alpha-1.0); // Get mult. factor
- beta = 1.0 - 0.5*(beta-1.0);
- m11 *= alpha; // Renormalize first column
- m21 *= alpha;
- m12 *= beta; // Renormalize second column
- m22 *= beta;
- alpha = m11*m12+m21*m22; // Columns' inner product
- alpha *= 0.5; // times 1/2
- register double temp;
- temp = m11-alpha*m12; // Subtract alpha times other column
- m12 -= alpha*m11;
- m11 = temp;
- temp = m21-alpha*m22;
- m22 -= alpha*m21;
- m11 = temp;
- return *this;
- }
- // Gives a measure of how far the matrix is from being normalized.
- // Mostly intended for diagnostic purposes.
- inline double NormalizeError( const Matrix2x2& A)
- {
- register double discrepancy;
- register double newdisc;
- discrepancy = A.m11*A.m11 + A.m21*A.m21 -1.0; // First column - inner product - 1
- if (discrepancy<0.0) {
- discrepancy = -discrepancy;
- }
- newdisc = A.m12*A.m12 + A.m22*A.m22 - 1.0; // Second column inner product - 1
- if ( newdisc<0.0 ) {
- newdisc = -newdisc;
- }
- if ( newdisc>discrepancy ) {
- discrepancy = newdisc;
- }
- newdisc = A.m11*A.m12 + A.m21*A.m22; // Inner product of two columns
- if ( newdisc<0.0 ) {
- newdisc = -newdisc;
- }
- if ( newdisc>discrepancy ) {
- discrepancy = newdisc;
- }
- return discrepancy;
- }
- inline VectorR2 operator* ( const Matrix2x2& A, const VectorR2& u)
- {
- return(VectorR2 ( A.m11*u.x + A.m12*u.y,
- A.m21*u.x + A.m22*u.y ) );
- }
-
- inline void Matrix2x2::Transform( VectorR2* u ) const {
- double newX;
- newX = m11*u->x + m12*u->y;
- u->y = m21*u->x + m22*u->y;
- u->x = newX;
- }
- inline void Matrix2x2::Transform( const VectorR2& src, VectorR2* dest ) const {
- dest->x = m11*src.x + m12*src.y;
- dest->y = m21*src.x + m22*src.y;
- }
- // ******************************************************
- // * LinearMapR2 class - inlined functions *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * **
- inline LinearMapR2::LinearMapR2()
- {
- SetZero();
- return;
- }
- inline LinearMapR2::LinearMapR2( const VectorR2& u, const VectorR2& v )
- :Matrix2x2 ( u, v )
- { }
- inline LinearMapR2::LinearMapR2(double a11, double a21, double a12, double a22)
- // Values specified in column order!!!
- :Matrix2x2 ( a11, a21, a12, a22 )
- { }
- inline LinearMapR2::LinearMapR2 ( const Matrix2x2& A )
- : Matrix2x2 (A)
- {}
- inline void LinearMapR2::Negate ()
- {
- m11 = -m11;
- m12 = -m12;
- m21 = -m21;
- m22 = -m22;
- }
-
- inline LinearMapR2& LinearMapR2::operator+= (const Matrix2x2& B)
- {
- m11 += B.m11;
- m12 += B.m12;
- m21 += B.m21;
- m22 += B.m22;
- return ( *this );
- }
- inline LinearMapR2& LinearMapR2::operator-= (const Matrix2x2& B)
- {
- m11 -= B.m11;
- m12 -= B.m12;
- m21 -= B.m21;
- m22 -= B.m22;
- return( *this );
- }
- inline LinearMapR2 operator+ (const LinearMapR2& A, const LinearMapR2& B)
- {
- return( LinearMapR2( A.m11+B.m11, A.m21+B.m21,
- A.m12+B.m12, A.m22+B.m22 ) );
- }
- inline LinearMapR2 operator- (const Matrix2x2& A)
- {
- return( LinearMapR2( -A.m11, -A.m21, -A.m12, -A.m22 ) );
- }
- inline LinearMapR2 operator- (const LinearMapR2& A, const LinearMapR2& B)
- {
- return( LinearMapR2( A.m11-B.m11, A.m21-B.m21,
- A.m12-B.m12, A.m22-B.m22 ) );
- }
- inline LinearMapR2& LinearMapR2::operator*= (register double b)
- {
- m11 *= b;
- m12 *= b;
- m21 *= b;
- m22 *= b;
- return ( *this);
- }
- inline LinearMapR2 operator* ( const LinearMapR2& A, register double b)
- {
- return( LinearMapR2( A.m11*b, A.m21*b,
- A.m12*b, A.m22*b ) );
- }
- inline LinearMapR2 operator* ( register double b, const LinearMapR2& A)
- {
- return( LinearMapR2( A.m11*b, A.m21*b,
- A.m12*b, A.m22*b ) );
- }
- inline LinearMapR2 operator/ ( const LinearMapR2& A, double b)
- {
- register double bInv = 1.0/b;
- return ( A*bInv );
- }
- inline LinearMapR2& LinearMapR2::operator/= (register double b)
- {
- register double bInv = 1.0/b;
- return ( *this *= bInv );
- }
- inline LinearMapR2 LinearMapR2::Transpose() const // Returns the transpose
- {
- return (LinearMapR2( m11, m12, m21, m22 ) );
- }
- inline LinearMapR2& LinearMapR2::operator*= (const Matrix2x2& B) // Matrix product
- {
- (*this).Matrix2x2::operator*=(B);
- return( *this );
- }
- inline LinearMapR2 operator* ( const LinearMapR2& A, const Matrix2x2& B)
- {
- LinearMapR2 AA(A);
- AA.Matrix2x2::operator*=(B);
- return AA;
- }
- inline LinearMapR2 operator* ( const Matrix2x2& A, const LinearMapR2& B)
- {
- LinearMapR2 AA(A);
- AA.Matrix2x2::operator*=(B);
- return AA;
- }
- inline LinearMapR2 operator* ( const LinearMapR2& A, const LinearMapR2& B)
- {
- LinearMapR2 AA(A);
- AA.Matrix2x2::operator*=(B);
- return AA;
- }
- inline double LinearMapR2::Determinant () const // Returns the determinant
- {
- return ( m11*m22 - m12*m21 );
- }
- // ******************************************************
- // * RotationMapR2 class - inlined functions *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * **
- inline RotationMapR2::RotationMapR2()
- {
- SetIdentity();
- return;
- }
-
- inline RotationMapR2::RotationMapR2( const VectorR2& u, const VectorR2& v )
- :Matrix2x2 ( u, v )
- { }
- inline RotationMapR2::RotationMapR2(
- double a11, double a21, double a12, double a22 )
- // Values specified in column order!!!
- :Matrix2x2 ( a11, a21, a12, a22 )
- { }
- inline RotationMapR2 RotationMapR2::Transpose() const // Returns the transpose
- {
- return ( RotationMapR2( m11, m12,
- m21, m22 ) );
- }
- inline VectorR2 RotationMapR2::Invert(const VectorR2& u) const // Returns solution
- {
- return (VectorR2( m11*u.x + m21*u.y, // Multiply with Transpose
- m12*u.x + m22*u.y ) );
- }
- inline RotationMapR2& RotationMapR2::operator*= (const RotationMapR2& B) // Matrix product
- {
- (*this).Matrix2x2::operator*=(B);
- return( *this );
- }
- inline RotationMapR2 operator* ( const RotationMapR2& A, const RotationMapR2& B)
- {
- RotationMapR2 AA(A);
- AA.Matrix2x2::operator*=(B);
- return AA;
- }
- // ***************************************************************
- // * 2-space vector and matrix utilities (inlined functions) *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Returns a righthanded orthonormal basis to complement vector u
- // The vector u must be unit.
- inline VectorR2 GetOrtho( const VectorR2& u )
- {
- return VectorR2 ( -u.y, u.x );
- }
- // Returns the projection of u onto unit v
- inline VectorR2 ProjectToUnit ( const VectorR2& u, const VectorR2& v)
- {
- return (u^v)*v;
- }
- // Returns the projection of u onto the plane perpindicular to the unit vector v
- inline VectorR2 ProjectPerpUnit ( const VectorR2& u, const VectorR2& v)
- {
- return ( u - ((u^v)*v) );
- }
- // Returns the projection of u onto the plane perpindicular to the unit vector v
- // This one is more stable when u and v are nearly equal.
- inline VectorR2 ProjectPerpUnitDiff ( const VectorR2& u, const VectorR2& v)
- {
- VectorR2 ans = u;
- ans -= v;
- ans -= ((ans^v)*v);
- return ans; // ans = (u-v) - ((u-v)^v)*v
- }
- // Returns the solid angle between vectors u and v.
- inline double Angle( const VectorR2& u, const VectorR2& v)
- {
- double nSqU = u.NormSq();
- double nSqV = v.NormSq();
- if ( nSqU==0.0 && nSqV==0.0 ) {
- return (0.0);
- }
- else {
- return ( AngleUnit( u/sqrt(nSqU), v/sqrt(nSqV) ) );
- }
- }
- inline double AngleUnit( const VectorR2& u, const VectorR2& v )
- {
- return ( atan2 ( (ProjectPerpUnit(v,u)).Norm(), u^v ) );
- }
- // Projection maps (LinearMapR2's)
- // VectorProjectMap returns map projecting onto a given vector u.
- // u should be a unit vector (otherwise the returned map is
- // scaled according to the magnitude of u.
- inline LinearMapR2 VectorProjectMap( const VectorR2& u )
- {
- double xy = u.x*u.y;
- return( LinearMapR2( u.x*u.x, xy, xy, u.y*u.y ) ) ;
- }
- // PlaneProjectMap returns map projecting onto a given plane.
- // The plane is the plane orthognal to u.
- // u must be a unit vector (otherwise the returned map is
- // garbage).
- inline LinearMapR2 PerpProjectMap ( const VectorR2& u )
- {
- double nxy = -u.x*u.y;
- return ( LinearMapR2 ( 1.0-u.x*u.x, nxy, nxy, 1.0-u.y*u.y ) );
- }
- // fromVec and toVec should be unit vectors
- inline RotationMapR2 RotateToMap( const VectorR2& fromVec, const VectorR2& toVec)
- {
- double costheta = fromVec.x*toVec.x + fromVec.y*toVec.y;
- double sintheta = fromVec.x*toVec.y - fromVec.y*toVec.x;
- return( RotationMapR2( costheta, sintheta, -sintheta, costheta ) );
- }
- #endif // LINEAR_R2_H
|