Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

include/cinder/Vector.h

Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 #pragma once
00024 
00025 #include <cmath>
00026 #include <cstring>
00027 #include <iostream>
00028 #include <cassert>
00029 #include <limits>
00030 
00031 #include "cinder/CinderMath.h"
00032 
00033 namespace cinder { 
00034 
00035 template<typename T, typename Y>
00036 struct VEC3CONV {
00037     static T    getX( const Y &v ) { return static_cast<T>( v.x ); }
00038     static T    getY( const Y &v ) { return static_cast<T>( v.y ); }
00039     static T    getZ( const Y &v ) { return static_cast<T>( v.z ); }        
00040 };
00041 
00042 template<typename T>
00043 class Vec2 
00044 {
00045  public:
00046     T x,y;
00047 
00048     typedef T TYPE;
00049     static const int DIM = 2;
00050 
00051     Vec2() {}
00052     Vec2( T nx, T ny ) : x( nx ), y( ny ) {}
00053     Vec2( const Vec2<T>& src ) : x( src.x ), y( src.y ) {}
00054     explicit Vec2( const T *d ) : x( d[0] ), y( d[1] ) {}
00055 
00056     template<typename FromT>
00057     Vec2( const Vec2<FromT>& src ) 
00058         : x( static_cast<T>( src.x ) ),y( static_cast<T>( src.y ) ) 
00059     {}
00060 
00061     void set( T ax, T ay )
00062     {
00063         x = ax; y = ay;
00064     }
00065 
00066     void set( const Vec2<T> &rhs )
00067     {
00068         x = rhs.x; y = rhs.y;
00069     }   
00070     
00071     // Operators
00072     template<typename FromT>
00073     Vec2<T>& operator=( const Vec2<FromT>& rhs )
00074     {
00075         x = static_cast<T>( rhs.x );
00076         y = static_cast<T>( rhs.y );
00077         return * this;
00078     }
00079 
00080     Vec2<T>& operator=( const Vec2<T>& rhs )
00081     {
00082         x = rhs.x;
00083         y = rhs.y;
00084         return * this;
00085     }
00086 
00087     T& operator[]( int n )
00088     {
00089         assert( n >= 0 && n <= 1 );
00090         return (&x)[n];
00091     }
00092 
00093     const T& operator[]( int n ) const
00094     {
00095         assert( n >= 0 && n <= 1 );
00096         return (&x)[n];
00097     }
00098 
00099     const Vec2<T>   operator+( const Vec2<T>& rhs ) const { return Vec2<T>( x + rhs.x, y + rhs.y ); }
00100     const Vec2<T>   operator-( const Vec2<T>& rhs ) const { return Vec2<T>( x - rhs.x, y - rhs.y ); }
00101     const Vec2<T>   operator*( const Vec2<T>& rhs ) const { return Vec2<T>( x * rhs.x, y * rhs.y ); }
00102     const Vec2<T>   operator/( const Vec2<T>& rhs ) const { return Vec2<T>( x / rhs.x, y / rhs.y ); }
00103     Vec2<T>&    operator+=( const Vec2<T>& rhs ) { x += rhs.x; y += rhs.y; return *this; }
00104     Vec2<T>&    operator-=( const Vec2<T>& rhs ) { x -= rhs.x; y -= rhs.y; return *this; }
00105     Vec2<T>&    operator*=( const Vec2<T>& rhs )    { x *= rhs.x; y *= rhs.y; return *this; }
00106     Vec2<T>&    operator/=( const Vec2<T>& rhs ) { x /= rhs.x; y /= rhs.y; return *this; }
00107     const Vec2<T>   operator/( T rhs ) const { return Vec2<T>( x / rhs, y / rhs ); }
00108     Vec2<T>&    operator+=( T rhs ) { x += rhs; y += rhs; return *this; }
00109     Vec2<T>&    operator-=( T rhs ) { x -= rhs; y -= rhs; return *this; }
00110     Vec2<T>&    operator*=( T rhs ) { x *= rhs; y *= rhs; return *this; }
00111     Vec2<T>&    operator/=( T rhs ) { x /= rhs; y /= rhs; return *this; }
00112     
00113     Vec2<T>     operator-() const { return Vec2<T>( -x, -y ); } // unary negation
00114 
00115     bool operator==( const Vec2<T> &rhs ) const 
00116     {
00117         return ( x == rhs.x ) && ( y == rhs.y ); 
00118     }
00119 
00120     bool operator!=( const Vec2<T> &rhs ) const
00121     { 
00122         return ! ( *this == rhs );
00123     }
00124 
00125     T dot( const Vec2<T> &rhs ) const
00126     {
00127         return x * rhs.x + y * rhs.y;
00128     }
00129 
00130     T distance( const Vec2<T> &rhs ) const
00131     {
00132         return ( *this - rhs ).length();
00133     }
00134 
00135     T distanceSquared( const Vec2<T> &rhs ) const
00136     {
00137         return ( *this - rhs ).lengthSquared();
00138     }
00139 
00140     T length() const
00141     {
00142         return (T)std::sqrt( x*x + y*y );
00143     }
00144 
00145     void normalize()
00146     {
00147         T invS = ((T)1) / length();
00148         x *= invS;
00149         y *= invS;
00150     }
00151 
00152     Vec2<T> normalized() const
00153     {
00154         T invS = ((T)1) / length();
00155         return Vec2<T>( x * invS, y * invS );
00156     }
00157 
00158     // tests for zero-length
00159     void safeNormalize()
00160     {
00161         T s = lengthSquared();
00162         if( s > 0 ) {
00163             T invL = ((T)1) / math<T>::sqrt( s );
00164             x *= invL;
00165             y *= invL;
00166         }
00167     }
00168 
00169     Vec2<T> safeNormalized()
00170     {
00171         T s = lengthSquared();
00172         if( s > 0 ) {
00173             T invL = ((T)1) / math<T>::sqrt( s );
00174             return Vec2<T>( x * invL, y * invL );
00175         }
00176         else
00177             return Vec2<T>::zero();
00178     }
00179 
00180     T lengthSquared() const
00181     {
00182         return x * x + y * y;
00183     }
00184 
00186     void limit( T maxLength ) 
00187     {
00188         T lengthSquared = x * x + y * y;
00189         
00190         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00191             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00192             x *= ratio;
00193             y *= ratio;
00194         }
00195     }
00196 
00198     Vec2<T> limited( T maxLength ) const
00199     {
00200         T lengthSquared = x * x + y * y;
00201         
00202         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00203             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00204             return Vec2<T>( x * ratio, y * ratio );
00205         }
00206         else
00207             return *this;
00208     }
00209 
00210     void invert()
00211     {
00212         x - -x;
00213         y = -y;
00214     }
00215     
00216     Vec2<T> inverse() const
00217     {
00218         return Vec2<T>( -x, -y );
00219     }
00220     
00221     Vec2<T> lerp( T fact, const Vec2<T>& r ) const
00222     {
00223         return (*this) + ( r - (*this) ) * fact;    
00224     }
00225 
00226     static Vec2<T> max()
00227     {
00228         return Vec2<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00229     }
00230 
00231     static Vec2<T> zero()
00232     {
00233         return Vec2<T>( static_cast<T>( 0 ), static_cast<T>( 0 ) );
00234     }
00235 
00236     static Vec2<T> one()
00237     {
00238         return Vec2<T>( static_cast<T>( 1 ), static_cast<T>( 1 ) );
00239     }
00240     
00241     operator T*(){ return (T*) this; }
00242     operator const T*() const { return (const T*) this; }
00243 
00244     friend std::ostream& operator<<( std::ostream& lhs, const Vec2<T>& rhs ) 
00245     {
00246         lhs << "[" << rhs.x << "," << rhs.y << "]";
00247         return lhs;
00248     }
00249     
00250     static Vec2<T> xAxis() { return Vec2<T>( 1, 0 ); }
00251     static Vec2<T> yAxis() { return Vec2<T>( 0, 1 ); }
00252 };
00253 
00254 template<typename T>
00255 class Vec3 
00256 {
00257 public:
00258     T x,y,z;
00259 
00260     typedef T TYPE;
00261     static const int DIM = 3;
00262 
00263     Vec3() {}
00264     Vec3( T nx, T ny, T nz ) 
00265         : x( nx ), y( ny ), z( nz )
00266     {}
00267     Vec3( const Vec3<T> &src ) 
00268         : x( src.x ), y( src.y ), z( src.z )
00269     {}
00270     Vec3( const Vec2<T> &v2, T aZ )
00271         : x( v2.x ), y ( v2.y ), z( aZ )
00272     {}
00273     explicit Vec3( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ) {}
00274     template<typename FromT>
00275     Vec3( const Vec3<FromT> &src )
00276         : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) )
00277     {}  
00278     template<typename Y>
00279     explicit Vec3( const Y &v )
00280         : x( VEC3CONV<Vec3<typename T::TYPE>,Y>::getX( v ) ), y( VEC3CONV<typename T::TYPE,Y>::getY( v ) ), z( VEC3CONV<typename T::TYPE,Y>::getZ( v ) )
00281     {
00282     }
00283 
00284     void set( T ax, T ay, T az )
00285     {
00286         x = ax; y = ay; z = az;
00287     }   
00288 
00289     void set( const Vec3<T> &rhs )
00290     {
00291         x = rhs.x; y = rhs.y; z = rhs.z;
00292     }       
00293     
00294     Vec3<T>& operator=( const Vec3<T> &rhs ) 
00295     {
00296         x = rhs.x;
00297         y = rhs.y;
00298         z = rhs.z;
00299         return * this;
00300     }
00301 
00302     template<typename FromT>
00303     Vec3<T>& operator=( const Vec3<FromT> &rhs )
00304     {
00305         x = static_cast<T>( rhs.x );
00306         y = static_cast<T>( rhs.y );
00307         z = static_cast<T>( rhs.z );
00308         return * this;
00309     }
00310 
00311     T& operator[]( int n )
00312     {
00313         assert( n >= 0 && n <= 2 );
00314         return (&x)[n];
00315     }
00316 
00317     const T& operator[]( int n ) const
00318     {
00319         assert( n >= 0 && n <= 2 );
00320         return (&x)[n];
00321     }
00322 
00323     const Vec3<T>   operator+( const Vec3<T>& rhs ) const { return Vec3<T>( x + rhs.x, y + rhs.y, z + rhs.z ); }
00324     const Vec3<T>   operator-( const Vec3<T>& rhs ) const { return Vec3<T>( x - rhs.x, y - rhs.y, z - rhs.z ); }
00325     const Vec3<T>   operator*( const Vec3<T>& rhs ) const { return Vec3<T>( x * rhs.x, y * rhs.y, z * rhs.z ); }
00326     const Vec3<T>   operator/( const Vec3<T>& rhs ) const { return Vec3<T>( x / rhs.x, y / rhs.y, z / rhs.z ); }
00327     Vec3<T>&    operator+=( const Vec3<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
00328     Vec3<T>&    operator-=( const Vec3<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }
00329     Vec3<T>&    operator*=( const Vec3<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this; }
00330     Vec3<T>&    operator/=( const Vec3<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; return *this; }
00331     const Vec3<T>   operator/( T rhs ) const { T invRhs = static_cast<T>( 1.0 ) / rhs; return Vec3<T>( x * invRhs, y * invRhs, z * invRhs ); }
00332     Vec3<T>&    operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; return *this; }
00333     Vec3<T>&    operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; return *this; }
00334     Vec3<T>&    operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; return *this; }
00335     Vec3<T>&    operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; return *this; }
00336 
00337     Vec3<T>     operator-() const { return Vec3<T>( -x, -y, -z ); } // unary negation
00338 
00339     bool operator==( const Vec3<T>& rhs ) const
00340     {
00341         return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ); 
00342     }
00343 
00344     bool operator!=( const Vec3<T>& rhs ) const 
00345     {
00346         return !( *this == rhs ); 
00347     }
00348 
00349     T dot( const Vec3<T> &rhs ) const
00350     {
00351         return x*rhs.x + y*rhs.y + z*rhs.z;
00352     }
00353 
00354     Vec3<T> cross( const Vec3<T> &rhs ) const 
00355     { 
00356         return Vec3<T>( y * rhs.z - rhs.y * z, z * rhs.x - rhs.z * x, x * rhs.y - rhs.x * y );
00357     }
00358 
00359     T distance( const Vec3<T> &rhs ) const
00360     {
00361         return ( *this - rhs ).length();
00362     }
00363 
00364     T distanceSquared( const Vec3<T> &rhs ) const
00365     {
00366         return ( *this - rhs ).lengthSquared();
00367     }
00368 
00369     T length() const 
00370     {
00371         return (T)std::sqrt( x*x + y*y + z*z );
00372     }
00373 
00374     T lengthSquared() const 
00375     {
00376         return x*x + y*y + z*z;
00377     }
00378 
00380     void limit( T maxLength ) 
00381     {
00382         T lengthSquared = x * x + y * y + z * z;
00383         
00384         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00385             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00386             x *= ratio;
00387             y *= ratio;
00388             z *= ratio;
00389         }
00390     }
00391 
00393     Vec3<T> limited( T maxLength ) const
00394     {
00395         T lengthSquared = x * x + y * y + z * z;
00396         
00397         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00398             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00399             return Vec3<T>( x * ratio, y * ratio, z * ratio );
00400         }
00401         else
00402             return *this;
00403     }
00404 
00405     void invert()
00406     {
00407         x - -x; y = -y; z = -z;
00408     }
00409     
00410     Vec3<T> inverse() const
00411     {
00412         return Vec3<T>( -x, -y, -z );
00413     }   
00414     
00415     void normalize() 
00416     {
00417         T invS = ((T)1) / length();
00418         x *= invS;
00419         y *= invS;
00420         z *= invS;
00421     }
00422 
00423     Vec3<T> normalized() const
00424     {
00425         T invS = ((T)1) / length();
00426         return Vec3<T>( x * invS, y * invS, z * invS );
00427     }
00428 
00429     // tests for zero-length
00430     void safeNormalize()
00431     {
00432         T s = lengthSquared();
00433         if( s > 0 ) {
00434             T invS = ((T)1) / math<T>::sqrt( s );
00435             x *= invS;
00436             y *= invS;
00437             z *= invS;
00438         }
00439     }
00440 
00441     Vec3<T> safeNormalized()
00442     {
00443         T s = lengthSquared();
00444         if( s > 0 ) {
00445             float invS = ((T)1) / math<T>::sqrt( s );
00446             return Vec3<T>( x * invS, y * invS, z * invS );
00447         }
00448         else
00449             return *this;
00450     }
00451     
00452     Vec3<T> randomOrthogonal() const
00453     {
00454         if( dot( Vec3<T>::xAxis() ) >= (T)0.01 ) {
00455             return cross( Vec3<T>::xAxis() );
00456         }
00457         else
00458             return cross( Vec3<T>::yAxis() );
00459     }
00460     
00461     void rotate( T ax, T ay, T az ) 
00462     {
00463         T a = cos( toRadians( ax ) );
00464         T b = sin( toRadians( ax ) );
00465         T c = cos( toRadians( ay ) );
00466         T d = sin( toRadians( ay ) );
00467         T e = cos( toRadians( az )  );
00468         T f = sin( toRadians( az ) );
00469         T nx = c*e*x - c*f*y + d*z;
00470         T ny = ( a*f + b*d*e ) * x + (a*e - b*d*f) * y - b*c*z;
00471         T nz = ( b*f - a*d*e ) * x + (a*d*f + b*e) * y + a*c*z;
00472         x = nx; 
00473         y = ny; 
00474         z = nz;
00475     }
00476 
00477     Vec3<T> lerp( T fact, const Vec3<T> &rhs ) const
00478     {
00479         return (*this) + (rhs - (*this)) * fact;
00480     }
00481 
00482     void lerpEq( T fact, const Vec3<T> &rhs )
00483     {
00484         x = x + ( rhs.x - x ) * fact; y = y + ( rhs.y - y ) * fact; z = z + ( rhs.z - z ) * fact;
00485     }   
00486     
00487     static Vec3<T> max()
00488     {
00489         return Vec3<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00490     }
00491 
00492     static Vec3<T> zero()
00493     {
00494         return Vec3<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00495     }
00496 
00497     static Vec3<T> one()
00498     {
00499         return Vec3<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) );
00500     }
00501 
00502     Vec3<T> slerp( T fact, const Vec3<T> &r ) const
00503     {
00504         T cosAlpha, alpha, sinAlpha;
00505         T t1, t2;
00506         Vec3<T> result;
00507 
00508         // get cosine of angle between vectors (-1 -> 1)
00509         cosAlpha = this->dot( r );
00510 
00511         // get angle (0 -> pi)
00512         alpha = math<T>::acos( cosAlpha );
00513 
00514         // get sine of angle between vectors (0 -> 1)
00515         sinAlpha = math<T>::sin( alpha );
00516 
00517         // this breaks down when sinAlpha = 0, i.e. alpha = 0 or pi
00518         t1 = math<T>::sin( ((T)1 - fact) * alpha) / sinAlpha;
00519         t2 = math<T>::sin( fact * alpha ) / sinAlpha;
00520 
00521         // interpolate src vectors
00522         return *this * t1 + r * t2;
00523     }
00524     
00525     // derived from but not equivalent to Quaternion::squad
00526     Vec3<T> squad( T t, const Vec3<T> &tangentA, const Vec3<T> &tangentB, const Vec3<T> &end )
00527     {
00528         Vec3<T> r1 = this->slerp( t, end ); 
00529         Vec3<T> r2 = tangentA.slerp( t, tangentB );
00530         return r1.slerp( 2 * t * (1-t), r2 );
00531     }
00532 
00533     operator T*(){ return (T*) this; }
00534     operator const T*() const { return (const T*) this; }
00535 
00536     friend std::ostream& operator<<( std::ostream& lhs, const Vec3<T> rhs ) 
00537     {
00538         lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z  << "]";
00539         return lhs;
00540     }
00541     
00542     static Vec3<T> xAxis() { return Vec3<T>( 1, 0, 0 ); }
00543     static Vec3<T> yAxis() { return Vec3<T>( 0, 1, 0 ); }
00544     static Vec3<T> zAxis() { return Vec3<T>( 0, 0, 1 ); }
00545 };
00546 
00547 template <class T>
00548 class Vec4{
00549  public:
00550     T x,y,z,w;
00551 
00552     typedef T TYPE;
00553     static const int DIM = 4;
00554 
00555     Vec4() 
00556         : x( 0 ), y( 0 ), z( 0 ), w( 0 )
00557     {}
00558     Vec4( T nx, T ny, T nz, T nw )
00559         : x( nx ), y( ny ), z( nz ), w( nw )
00560     {}
00561     Vec4( const Vec3<T>& src, T aW ) 
00562         : x( src.x ), y( src.y ), z( src.z ), w( aW )
00563     {}
00564     Vec4( const Vec4<T>& src ) 
00565         : x( src.x ), y( src.y ), z( src.z ), w( src.w )
00566     {}
00567     template<typename FromT>
00568     Vec4( const Vec4<FromT>& src )
00569         : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ),w( static_cast<T>( src.w ) )
00570     {}
00571     explicit Vec4( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ), w( d[3] ) {}
00572 
00573     Vec4<T>& operator=( const Vec4<T>& rhs ) 
00574     {
00575         x = rhs.x; y = rhs.y; z = rhs.z; w = rhs.w;
00576         return *this;
00577     }
00578 
00579     template<typename FromT>
00580     Vec4<T>& operator=( const Vec4<FromT>& rhs ) 
00581     {
00582         x = static_cast<T>(rhs.x); y = static_cast<T>(rhs.y); z = static_cast<T>(rhs.z); w = static_cast<T>(rhs.w);
00583         return *this;
00584     }
00585 
00586     T& operator[]( int n ) 
00587     {
00588         assert( n >= 0 && n <= 3 );
00589         return (&x)[n];
00590     }
00591 
00592     const T& operator[]( int n )  const
00593     {
00594         assert( n >= 0 && n <= 3 );
00595         return (&x)[n];
00596     }
00597 
00598     const Vec4<T>   operator+( const Vec4<T>& rhs ) const { return Vec4<T>( x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w ); }
00599     const Vec4<T>   operator-( const Vec4<T>& rhs ) const { return Vec4<T>( x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w ); }
00600     const Vec4<T>   operator*( const Vec4<T>& rhs ) const { return Vec4<T>( x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w ); }
00601     const Vec4<T>   operator/( const Vec4<T>& rhs ) const { return Vec4<T>( x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w ); }
00602     Vec4<T>&    operator+=( const Vec4<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; }
00603     Vec4<T>&    operator-=( const Vec4<T>& rhs ) {  x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; }
00604     Vec4<T>&    operator*=( const Vec4<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z;  w *= rhs.w; return *this; }
00605     Vec4<T>&    operator/=( const Vec4<T>& rhs ) {  x /= rhs.x; y /= rhs.y; z /= rhs.z; w /= rhs.w; return *this; }
00606     const Vec4<T>   operator/( T rhs ) const { return Vec4<T>( x / rhs, y / rhs, z / rhs, w / rhs ); }
00607     Vec4<T>&    operator+=( T rhs ) {   x += rhs; y += rhs; z += rhs; w += rhs; return *this; }
00608     Vec4<T>&    operator-=( T rhs ) {   x -= rhs; y -= rhs; z -= rhs; w -= rhs; return * this; }
00609     Vec4<T>&    operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; w *= rhs; return * this; }
00610     Vec4<T>&    operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; w /= rhs;   return * this; }
00611 
00612     Vec4<T>  operator-() const { return Vec4<T>( -x, -y, -z, -w ); } // unary negation
00613 
00614     bool operator==( const Vec4<T>& rhs ) const 
00615     {
00616         return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ) && ( w == rhs.w ); 
00617     }
00618 
00619     bool operator!=( const Vec4<T>& rhs ) const { return ! (*this == rhs); }
00620 
00621     T length() const
00622     {
00623         return (T)std::sqrt(x * x + y * y + z * z + w * w);
00624     }
00625 
00626     void normalize() 
00627     {
00628         T invS = ((T)1) / length();
00629         x *= invS;
00630         y *= invS;
00631         z *= invS;
00632         w *= invS;
00633     }
00634 
00635     // tests for zero-length
00636     void safeNormalize()
00637     {
00638         T s = lengthSquared();
00639         if( s > 0 ) {
00640             T invS = ((T)1) / math<T>::sqrt( s );
00641             x *= invS;
00642             y *= invS;
00643             z *= invS;
00644             w *= invS;
00645         }
00646     }
00647 
00648     T lengthSquared() const 
00649     {
00650         return x * x + y * y + z * z + w * w;
00651     }
00652 
00654     void limit( T maxLength ) 
00655     {
00656         T lengthSquared = x * x + y * y + z * z + w * w;
00657         
00658         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00659             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00660             x *= ratio;
00661             y *= ratio;
00662             z *= ratio;
00663             w *= ratio;
00664         }
00665     }
00666 
00668     Vec4<T> limited( T maxLength ) const
00669     {
00670         T lengthSquared = x * x + y * y + z * z + w * w;
00671         
00672         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00673             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00674             return Vec4<T>( x * ratio, y * ratio, z * ratio, w * ratio );
00675         }
00676         else
00677             return *this;
00678     }
00679 
00680     void invert()
00681     {
00682         x - -x; y = -y; z = -z; w = -w;
00683     }
00684     
00685     Vec4<T> inverse() const
00686     {
00687         return Vec3<T>( -x, -y, -z, -w );
00688     }   
00689 
00690 
00691     Vec4<T> lerp( T fact, const Vec4<T>& r ) const
00692     {
00693         return (*this) + ( r - (*this) ) * fact;    
00694     }
00695 
00696     static Vec4<T> max()
00697     {
00698         return Vec4<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00699     }
00700     
00701     static Vec4<T> zero()
00702     {
00703         return Vec4<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00704     }   
00705 
00706     static Vec4<T> one()
00707     {
00708         return Vec4<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) );
00709     }   
00710 
00711     operator T*(){ return (T*) this; }
00712     operator const T*() const { return (const T*) this; }
00713 
00714     friend std::ostream& operator<<( std::ostream& lhs, const Vec4<T>& rhs ) 
00715     {
00716         lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "," << rhs.w << "]";
00717         return lhs;
00718     }
00719     
00720     static Vec4<T> xAxis() { return Vec4<T>( 1, 0, 0, 0 ); }
00721     static Vec4<T> yAxis() { return Vec4<T>( 0, 1, 0, 0 ); }
00722     static Vec4<T> zAxis() { return Vec4<T>( 0, 0, 1, 0 ); }    
00723     static Vec4<T> wAxis() { return Vec4<T>( 0, 0, 0, 1 ); }        
00724 };
00725 
00726 template<typename T,typename Y> inline Vec2<T> operator *( Y s, const Vec2<T> &v ) { return Vec2<T>( v.x * s, v.y * s ); }
00727 template<typename T,typename Y> inline Vec2<T> operator *( const Vec2<T> &v, Y s ) { return Vec2<T>( v.x * s, v.y * s ); }
00728 template<typename T,typename Y> inline Vec3<T> operator *( Y s, const Vec3<T> &v ) { return Vec3<T>( v.x * s, v.y * s, v.z * s ); }
00729 template<typename T,typename Y> inline Vec3<T> operator *( const Vec3<T> &v, Y s ) { return Vec3<T>( v.x * s, v.y * s, v.z * s ); }
00730 template<typename T,typename Y> inline Vec4<T> operator *( Y s, const Vec4<T> &v ) { return Vec4<T>( v.x * s, v.y * s, v.z * s, v.w * s ); }
00731 template<typename T,typename Y> inline Vec4<T> operator *( const Vec4<T> &v, Y s ) { return Vec4<T>( v.x * s, v.y * s, v.z * s, v.w * s ); }
00732 
00733 
00734 typedef Vec2<float>     Vec2f;
00735 typedef Vec2<double>    Vec2d;
00736 typedef Vec3<float>     Vec3f;
00737 typedef Vec3<double>    Vec3d;
00738 typedef Vec4<float>     Vec4f;
00739 typedef Vec4<double>    Vec4d;
00740 typedef Vec2<int>       Vec2i;
00741 
00742 } // namespace cinder