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 math<T>::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     void rotate(T angle)
00181     {
00182         T cosa = math<T>::cos( angle );
00183         T sina = math<T>::sin( angle );
00184         T rx = x * cosa - y * sina;
00185         y = x * sina + y * cosa;
00186         x = rx;
00187     }
00188 
00189     T lengthSquared() const
00190     {
00191         return x * x + y * y;
00192     }
00193 
00195     void limit( T maxLength )
00196     {
00197         T lengthSquared = x * x + y * y;
00198 
00199         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00200             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00201             x *= ratio;
00202             y *= ratio;
00203         }
00204     }
00205 
00207     Vec2<T> limited( T maxLength ) const
00208     {
00209         T lengthSquared = x * x + y * y;
00210 
00211         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00212             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00213             return Vec2<T>( x * ratio, y * ratio );
00214         }
00215         else
00216             return *this;
00217     }
00218 
00219     void invert()
00220     {
00221         x = -x;
00222         y = -y;
00223     }
00224 
00225     Vec2<T> inverse() const
00226     {
00227         return Vec2<T>( -x, -y );
00228     }
00229 
00230     Vec2<T> lerp( T fact, const Vec2<T>& r ) const
00231     {
00232         return (*this) + ( r - (*this) ) * fact;
00233     }
00234 
00235     static Vec2<T> max()
00236     {
00237         return Vec2<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00238     }
00239 
00240     static Vec2<T> zero()
00241     {
00242         return Vec2<T>( static_cast<T>( 0 ), static_cast<T>( 0 ) );
00243     }
00244 
00245     static Vec2<T> one()
00246     {
00247         return Vec2<T>( static_cast<T>( 1 ), static_cast<T>( 1 ) );
00248     }
00249 
00250     operator T*(){ return (T*) this; }
00251     operator const T*() const { return (const T*) this; }
00252 
00253     friend std::ostream& operator<<( std::ostream& lhs, const Vec2<T>& rhs )
00254     {
00255         lhs << "[" << rhs.x << "," << rhs.y << "]";
00256         return lhs;
00257     }
00258 
00259     static Vec2<T> xAxis() { return Vec2<T>( 1, 0 ); }
00260     static Vec2<T> yAxis() { return Vec2<T>( 0, 1 ); }
00261 };
00262 
00263 template<typename T>
00264 class Vec3
00265 {
00266 public:
00267     T x,y,z;
00268 
00269     typedef T TYPE;
00270     static const int DIM = 3;
00271 
00272     Vec3() {}
00273     Vec3( T nx, T ny, T nz )
00274         : x( nx ), y( ny ), z( nz )
00275     {}
00276     Vec3( const Vec3<T> &src )
00277         : x( src.x ), y( src.y ), z( src.z )
00278     {}
00279     Vec3( const Vec2<T> &v2, T aZ )
00280         : x( v2.x ), y ( v2.y ), z( aZ )
00281     {}
00282     explicit Vec3( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ) {}
00283     template<typename FromT>
00284     Vec3( const Vec3<FromT> &src )
00285         : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) )
00286     {}
00287     template<typename Y>
00288     explicit Vec3( const Y &v )
00289         : 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 ) )
00290     {
00291     }
00292 
00293     void set( T ax, T ay, T az )
00294     {
00295         x = ax; y = ay; z = az;
00296     }
00297 
00298     void set( const Vec3<T> &rhs )
00299     {
00300         x = rhs.x; y = rhs.y; z = rhs.z;
00301     }
00302 
00303     Vec3<T>& operator=( const Vec3<T> &rhs )
00304     {
00305         x = rhs.x;
00306         y = rhs.y;
00307         z = rhs.z;
00308         return * this;
00309     }
00310 
00311     template<typename FromT>
00312     Vec3<T>& operator=( const Vec3<FromT> &rhs )
00313     {
00314         x = static_cast<T>( rhs.x );
00315         y = static_cast<T>( rhs.y );
00316         z = static_cast<T>( rhs.z );
00317         return * this;
00318     }
00319 
00320     T& operator[]( int n )
00321     {
00322         assert( n >= 0 && n <= 2 );
00323         return (&x)[n];
00324     }
00325 
00326     const T& operator[]( int n ) const
00327     {
00328         assert( n >= 0 && n <= 2 );
00329         return (&x)[n];
00330     }
00331 
00332     const Vec3<T>   operator+( const Vec3<T>& rhs ) const { return Vec3<T>( x + rhs.x, y + rhs.y, z + rhs.z ); }
00333     const Vec3<T>   operator-( const Vec3<T>& rhs ) const { return Vec3<T>( x - rhs.x, y - rhs.y, z - rhs.z ); }
00334     const Vec3<T>   operator*( const Vec3<T>& rhs ) const { return Vec3<T>( x * rhs.x, y * rhs.y, z * rhs.z ); }
00335     const Vec3<T>   operator/( const Vec3<T>& rhs ) const { return Vec3<T>( x / rhs.x, y / rhs.y, z / rhs.z ); }
00336     Vec3<T>&    operator+=( const Vec3<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
00337     Vec3<T>&    operator-=( const Vec3<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }
00338     Vec3<T>&    operator*=( const Vec3<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this; }
00339     Vec3<T>&    operator/=( const Vec3<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; return *this; }
00340     const Vec3<T>   operator/( T rhs ) const { T invRhs = static_cast<T>( 1.0 ) / rhs; return Vec3<T>( x * invRhs, y * invRhs, z * invRhs ); }
00341     Vec3<T>&    operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; return *this; }
00342     Vec3<T>&    operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; return *this; }
00343     Vec3<T>&    operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; return *this; }
00344     Vec3<T>&    operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; return *this; }
00345 
00346     Vec3<T>     operator-() const { return Vec3<T>( -x, -y, -z ); } // unary negation
00347 
00348     bool operator==( const Vec3<T>& rhs ) const
00349     {
00350         return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z );
00351     }
00352 
00353     bool operator!=( const Vec3<T>& rhs ) const
00354     {
00355         return !( *this == rhs );
00356     }
00357 
00358     T dot( const Vec3<T> &rhs ) const
00359     {
00360         return x*rhs.x + y*rhs.y + z*rhs.z;
00361     }
00362 
00363     Vec3<T> cross( const Vec3<T> &rhs ) const
00364     {
00365         return Vec3<T>( y * rhs.z - rhs.y * z, z * rhs.x - rhs.z * x, x * rhs.y - rhs.x * y );
00366     }
00367 
00368     T distance( const Vec3<T> &rhs ) const
00369     {
00370         return ( *this - rhs ).length();
00371     }
00372 
00373     T distanceSquared( const Vec3<T> &rhs ) const
00374     {
00375         return ( *this - rhs ).lengthSquared();
00376     }
00377 
00378     T length() const
00379     {
00380         return math<T>::sqrt( x*x + y*y + z*z );
00381     }
00382 
00383     T lengthSquared() const
00384     {
00385         return x*x + y*y + z*z;
00386     }
00387 
00389     void limit( T maxLength )
00390     {
00391         T lengthSquared = x * x + y * y + z * z;
00392 
00393         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00394             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00395             x *= ratio;
00396             y *= ratio;
00397             z *= ratio;
00398         }
00399     }
00400 
00402     Vec3<T> limited( T maxLength ) const
00403     {
00404         T lengthSquared = x * x + y * y + z * z;
00405 
00406         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00407             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00408             return Vec3<T>( x * ratio, y * ratio, z * ratio );
00409         }
00410         else
00411             return *this;
00412     }
00413 
00414     void invert()
00415     {
00416         x = -x; y = -y; z = -z;
00417     }
00418 
00419     Vec3<T> inverse() const
00420     {
00421         return Vec3<T>( -x, -y, -z );
00422     }
00423 
00424     void normalize()
00425     {
00426         T invS = ((T)1) / length();
00427         x *= invS;
00428         y *= invS;
00429         z *= invS;
00430     }
00431 
00432     Vec3<T> normalized() const
00433     {
00434         T invS = ((T)1) / length();
00435         return Vec3<T>( x * invS, y * invS, z * invS );
00436     }
00437 
00438     // tests for zero-length
00439     void safeNormalize()
00440     {
00441         T s = lengthSquared();
00442         if( s > 0 ) {
00443             T invS = ((T)1) / math<T>::sqrt( s );
00444             x *= invS;
00445             y *= invS;
00446             z *= invS;
00447         }
00448     }
00449 
00450     Vec3<T> safeNormalized()
00451     {
00452         T s = lengthSquared();
00453         if( s > 0 ) {
00454             float invS = ((T)1) / math<T>::sqrt( s );
00455             return Vec3<T>( x * invS, y * invS, z * invS );
00456         }
00457         else
00458             return *this;
00459     }
00460 
00461     Vec3<T> randomOrthogonal() const
00462     {
00463         if( dot( Vec3<T>::xAxis() ) >= (T)0.01 ) {
00464             return cross( Vec3<T>::xAxis() );
00465         }
00466         else
00467             return cross( Vec3<T>::yAxis() );
00468     }
00469 
00470     void rotateX( T angle )
00471     {
00472         T sina = math<T>::sin(angle);
00473         T cosa = math<T>::cos(angle);
00474         T ry = y * cosa - z * sina;
00475         T rz = y * sina + z * cosa;
00476         y = ry;
00477         z = rz;
00478     }
00479 
00480     void rotateY( T angle )
00481     {
00482         T sina = math<T>::sin(angle);
00483         T cosa = math<T>::cos(angle);
00484         T rx = x * cosa - z * sina;
00485         T rz = x * sina + z * cosa;
00486         x = rx;
00487         z = rz;
00488     }
00489 
00490     void rotateZ( T angle )
00491     {
00492         T sina = math<T>::sin(angle);
00493         T cosa = math<T>::cos(angle);
00494         T rx = x * cosa - y * sina;
00495         T ry = x * sina + y * cosa;
00496         x = rx;
00497         y = ry;
00498     }
00499 
00500     void rotate( Vec3<T> axis, T angle )
00501     {
00502         T cosa = math<T>::cos(angle);
00503         T sina = math<T>::sin(angle);
00504 
00505         T rx = (cosa + (1 - cosa) * axis.x * axis.x) * x;
00506         rx += ((1 - cosa) * axis.x * axis.y - axis.z * sina) * y;
00507         rx += ((1 - cosa) * axis.x * axis.z + axis.y * sina) * z;
00508 
00509         T ry = ((1 - cosa) * axis.x * axis.y + axis.z * sina) * x;
00510         ry += (cosa + (1 - cosa) * axis.y * axis.y) * y;
00511         ry += ((1 - cosa) * axis.y * axis.z - axis.x * sina) * z;
00512 
00513         T rz = ((1 - cosa) * axis.x * axis.z - axis.y * sina) * x;
00514         rz += ((1 - cosa) * axis.y * axis.z + axis.x * sina) * y;
00515         rz += (cosa + (1 - cosa) * axis.z * axis.z) * z;
00516 
00517         x = rx;
00518         y = ry;
00519         z = rz;
00520     }
00521 
00522     Vec3<T> lerp( T fact, const Vec3<T> &rhs ) const
00523     {
00524         return (*this) + (rhs - (*this)) * fact;
00525     }
00526 
00527     void lerpEq( T fact, const Vec3<T> &rhs )
00528     {
00529         x = x + ( rhs.x - x ) * fact; y = y + ( rhs.y - y ) * fact; z = z + ( rhs.z - z ) * fact;
00530     }
00531 
00532     static Vec3<T> max()
00533     {
00534         return Vec3<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00535     }
00536 
00537     static Vec3<T> zero()
00538     {
00539         return Vec3<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00540     }
00541 
00542     static Vec3<T> one()
00543     {
00544         return Vec3<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) );
00545     }
00546 
00547     Vec3<T> slerp( T fact, const Vec3<T> &r ) const
00548     {
00549         T cosAlpha, alpha, sinAlpha;
00550         T t1, t2;
00551         Vec3<T> result;
00552 
00553         // get cosine of angle between vectors (-1 -> 1)
00554         cosAlpha = this->dot( r );
00555 
00556         // get angle (0 -> pi)
00557         alpha = math<T>::acos( cosAlpha );
00558 
00559         // get sine of angle between vectors (0 -> 1)
00560         sinAlpha = math<T>::sin( alpha );
00561 
00562         // this breaks down when sinAlpha = 0, i.e. alpha = 0 or pi
00563         t1 = math<T>::sin( ((T)1 - fact) * alpha) / sinAlpha;
00564         t2 = math<T>::sin( fact * alpha ) / sinAlpha;
00565 
00566         // interpolate src vectors
00567         return *this * t1 + r * t2;
00568     }
00569 
00570     // derived from but not equivalent to Quaternion::squad
00571     Vec3<T> squad( T t, const Vec3<T> &tangentA, const Vec3<T> &tangentB, const Vec3<T> &end )
00572     {
00573         Vec3<T> r1 = this->slerp( t, end );
00574         Vec3<T> r2 = tangentA.slerp( t, tangentB );
00575         return r1.slerp( 2 * t * (1-t), r2 );
00576     }
00577 
00578     operator T*(){ return (T*) this; }
00579     operator const T*() const { return (const T*) this; }
00580 
00581     friend std::ostream& operator<<( std::ostream& lhs, const Vec3<T> rhs )
00582     {
00583         lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z  << "]";
00584         return lhs;
00585     }
00586 
00587     static Vec3<T> xAxis() { return Vec3<T>( 1, 0, 0 ); }
00588     static Vec3<T> yAxis() { return Vec3<T>( 0, 1, 0 ); }
00589     static Vec3<T> zAxis() { return Vec3<T>( 0, 0, 1 ); }
00590 };
00591 
00592 template <class T>
00593 class Vec4{
00594  public:
00595     T x,y,z,w;
00596 
00597     typedef T TYPE;
00598     static const int DIM = 4;
00599 
00600     Vec4()
00601         : x( 0 ), y( 0 ), z( 0 ), w( 0 )
00602     {}
00603     Vec4( T nx, T ny, T nz, T nw )
00604         : x( nx ), y( ny ), z( nz ), w( nw )
00605     {}
00606     Vec4( const Vec3<T>& src, T aW )
00607         : x( src.x ), y( src.y ), z( src.z ), w( aW )
00608     {}
00609     Vec4( const Vec4<T>& src )
00610         : x( src.x ), y( src.y ), z( src.z ), w( src.w )
00611     {}
00612     template<typename FromT>
00613     Vec4( const Vec4<FromT>& src )
00614         : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ),w( static_cast<T>( src.w ) )
00615     {}
00616     explicit Vec4( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ), w( d[3] ) {}
00617 
00618     Vec4<T>& operator=( const Vec4<T>& rhs )
00619     {
00620         x = rhs.x; y = rhs.y; z = rhs.z; w = rhs.w;
00621         return *this;
00622     }
00623 
00624     template<typename FromT>
00625     Vec4<T>& operator=( const Vec4<FromT>& rhs )
00626     {
00627         x = static_cast<T>(rhs.x); y = static_cast<T>(rhs.y); z = static_cast<T>(rhs.z); w = static_cast<T>(rhs.w);
00628         return *this;
00629     }
00630 
00631     T& operator[]( int n )
00632     {
00633         assert( n >= 0 && n <= 3 );
00634         return (&x)[n];
00635     }
00636 
00637     const T& operator[]( int n )  const
00638     {
00639         assert( n >= 0 && n <= 3 );
00640         return (&x)[n];
00641     }
00642 
00643     const Vec4<T>   operator+( const Vec4<T>& rhs ) const { return Vec4<T>( x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w ); }
00644     const Vec4<T>   operator-( const Vec4<T>& rhs ) const { return Vec4<T>( x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w ); }
00645     const Vec4<T>   operator*( const Vec4<T>& rhs ) const { return Vec4<T>( x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w ); }
00646     const Vec4<T>   operator/( const Vec4<T>& rhs ) const { return Vec4<T>( x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w ); }
00647     Vec4<T>&    operator+=( const Vec4<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; }
00648     Vec4<T>&    operator-=( const Vec4<T>& rhs ) {  x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; }
00649     Vec4<T>&    operator*=( const Vec4<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z;  w *= rhs.w; return *this; }
00650     Vec4<T>&    operator/=( const Vec4<T>& rhs ) {  x /= rhs.x; y /= rhs.y; z /= rhs.z; w /= rhs.w; return *this; }
00651     const Vec4<T>   operator/( T rhs ) const { return Vec4<T>( x / rhs, y / rhs, z / rhs, w / rhs ); }
00652     Vec4<T>&    operator+=( T rhs ) {   x += rhs; y += rhs; z += rhs; w += rhs; return *this; }
00653     Vec4<T>&    operator-=( T rhs ) {   x -= rhs; y -= rhs; z -= rhs; w -= rhs; return * this; }
00654     Vec4<T>&    operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; w *= rhs; return * this; }
00655     Vec4<T>&    operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; w /= rhs;   return * this; }
00656 
00657     Vec4<T>  operator-() const { return Vec4<T>( -x, -y, -z, -w ); } // unary negation
00658 
00659     bool operator==( const Vec4<T>& rhs ) const
00660     {
00661         return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ) && ( w == rhs.w );
00662     }
00663 
00664     bool operator!=( const Vec4<T>& rhs ) const { return ! (*this == rhs); }
00665 
00666     T length() const
00667     {
00668         return math<float>::sqrt(x * x + y * y + z * z + w * w);
00669     }
00670 
00671     void normalize()
00672     {
00673         T invS = ((T)1) / length();
00674         x *= invS;
00675         y *= invS;
00676         z *= invS;
00677         w *= invS;
00678     }
00679 
00680     // tests for zero-length
00681     void safeNormalize()
00682     {
00683         T s = lengthSquared();
00684         if( s > 0 ) {
00685             T invS = ((T)1) / math<T>::sqrt( s );
00686             x *= invS;
00687             y *= invS;
00688             z *= invS;
00689             w *= invS;
00690         }
00691     }
00692 
00693     T lengthSquared() const
00694     {
00695         return x * x + y * y + z * z + w * w;
00696     }
00697 
00699     void limit( T maxLength )
00700     {
00701         T lengthSquared = x * x + y * y + z * z + w * w;
00702 
00703         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00704             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00705             x *= ratio;
00706             y *= ratio;
00707             z *= ratio;
00708             w *= ratio;
00709         }
00710     }
00711 
00713     Vec4<T> limited( T maxLength ) const
00714     {
00715         T lengthSquared = x * x + y * y + z * z + w * w;
00716 
00717         if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) {
00718             T ratio = maxLength / math<T>::sqrt( lengthSquared );
00719             return Vec4<T>( x * ratio, y * ratio, z * ratio, w * ratio );
00720         }
00721         else
00722             return *this;
00723     }
00724 
00725     void invert()
00726     {
00727         x = -x; y = -y; z = -z; w = -w;
00728     }
00729 
00730     Vec4<T> inverse() const
00731     {
00732         return Vec3<T>( -x, -y, -z, -w );
00733     }
00734 
00735 
00736     Vec4<T> lerp( T fact, const Vec4<T>& r ) const
00737     {
00738         return (*this) + ( r - (*this) ) * fact;
00739     }
00740 
00741     static Vec4<T> max()
00742     {
00743         return Vec4<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00744     }
00745 
00746     static Vec4<T> zero()
00747     {
00748         return Vec4<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00749     }
00750 
00751     static Vec4<T> one()
00752     {
00753         return Vec4<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) );
00754     }
00755 
00756     operator T*(){ return (T*) this; }
00757     operator const T*() const { return (const T*) this; }
00758 
00759     friend std::ostream& operator<<( std::ostream& lhs, const Vec4<T>& rhs )
00760     {
00761         lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "," << rhs.w << "]";
00762         return lhs;
00763     }
00764 
00765     static Vec4<T> xAxis() { return Vec4<T>( 1, 0, 0, 0 ); }
00766     static Vec4<T> yAxis() { return Vec4<T>( 0, 1, 0, 0 ); }
00767     static Vec4<T> zAxis() { return Vec4<T>( 0, 0, 1, 0 ); }
00768     static Vec4<T> wAxis() { return Vec4<T>( 0, 0, 0, 1 ); }
00769 };
00770 
00772 template<typename T>
00773 Vec2<T> toPolar( Vec2<T> car )
00774 {
00775     const T epsilon = (T)0.0000001;
00776     T theta;
00777     if( math<T>::abs( car.x ) < epsilon ) { // x == 0
00778         if( math<T>::abs( car.y ) < epsilon ) theta = 0;
00779         else if( car.y > 0 ) theta = (T)M_PI / 2;
00780         else theta = ( (T)M_PI * 3 ) / 2;
00781     }
00782     else if ( car.x > 0 ) {
00783         if( car.y < 0 ) theta = math<T>::atan( car.y / car.x ) + 2 * (T)M_PI;
00784         else theta = math<T>::atan( car.y / car.x );
00785     }
00786     else // car.x < 0
00787         theta = (math<T>::atan( car.y / car.x ) + M_PI );
00788 
00789     return Vec2<T>( car.length(), theta );
00790 }
00791 
00793 template<typename T>
00794 Vec2<T> fromPolar( Vec2<T> pol )
00795 {
00796     return Vec2<T>( math<T>::cos( pol.y ) *  pol.x , math<T>::sin( pol.y ) *  pol.x );
00797 }
00798 
00799 template<typename T,typename Y> inline Vec2<T> operator *( Y s, const Vec2<T> &v ) { return Vec2<T>( v.x * s, v.y * s ); }
00800 template<typename T,typename Y> inline Vec2<T> operator *( const Vec2<T> &v, Y s ) { return Vec2<T>( v.x * s, v.y * s ); }
00801 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 ); }
00802 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 ); }
00803 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 ); }
00804 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 ); }
00805 
00806 
00807 typedef Vec2<float>     Vec2f;
00808 typedef Vec2<double>    Vec2d;
00809 typedef Vec3<float>     Vec3f;
00810 typedef Vec3<double>    Vec3d;
00811 typedef Vec4<float>     Vec4f;
00812 typedef Vec4<double>    Vec4d;
00813 typedef Vec2<int>       Vec2i;
00814 
00815 } // namespace cinder