Sirikata
libcore/include/sirikata/core/util/Vector3.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Vector3.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 #ifndef _SIRIKATA_VECTOR3_HPP_
00033 #define _SIRIKATA_VECTOR3_HPP_
00034 
00035 #include <string>
00036 #include <cassert>
00037 #include <sstream>
00038 
00039 #include <boost/functional/hash.hpp>
00040 
00041 namespace Sirikata {
00042 template <typename scalar> class Vector3 {
00043 public:
00044     static const unsigned char size = 3;
00045     typedef scalar real;
00046     union {
00047         struct {
00048             scalar x;
00049             scalar y;
00050             scalar z;
00051         };
00052         scalar v[3];
00053     };
00054     Vector3(scalar x, scalar y, scalar z) {
00055         this->x=x;
00056         this->y=y;
00057         this->z=z;
00058     }
00059     template <class V> explicit Vector3(const V&other) {
00060         x=other[0];
00061         y=other[1];
00062         z=other[2];
00063     }
00064     Vector3(){}
00065     template <class V> static Vector3 fromSSE(const V&other){
00066         return Vector3(other.x(),other.y(),other.z());
00067     }
00068     scalar&operator[](const unsigned int i) {
00069         assert(i<3);
00070         return v[i];
00071     }
00072 #if 0
00073     template<class T> operator T() const{
00074         return T(x,y,z);
00075     }
00076 #else
00077     template<class T> T convert() const{
00078         return T(x,y,z);
00079     }
00080 #endif
00081     template<class T> Vector3<T> downCast() const{
00082         return Vector3<T>((T)x,(T)y,(T)z);
00083     }
00084 
00085     scalar operator[](const unsigned int i) const{
00086         assert(i<3);
00087         return v[i];
00088     }
00089     Vector3&operator=(scalar other) {
00090         x=other;
00091         y=other;
00092         z=other;
00093         return *this;
00094     }
00095     static Vector3 zero() {
00096         return Vector3(0,0,0);
00097     }
00098     static Vector3 unitX() {
00099         return Vector3(1,0,0);
00100     }
00101     static Vector3 unitY() {
00102         return Vector3(0,1,0);
00103     }
00104     static Vector3 unitZ() {
00105         return Vector3(0,0,1);
00106     }
00107     static Vector3 unitNegX() {
00108         return Vector3(-1,0,0);
00109     }
00110     static Vector3 unitNegY() {
00111         return Vector3(0,-1,0);
00112     }
00113     static Vector3 unitNegZ() {
00114         return Vector3(0,0,-1);
00115     }
00116     Vector3 operator*(scalar scale) const {
00117         return Vector3(x*scale,y*scale,z*scale);
00118     }
00119     Vector3 scale(scalar scale) const { return (*this)*scale; }
00120     Vector3 operator/(scalar scale) const {
00121         return Vector3(x/scale,y/scale,z/scale);
00122     }
00123     Vector3 operator+(const Vector3&other) const {
00124         return Vector3(x+other.x,y+other.y,z+other.z);
00125     }
00126     Vector3 componentMultiply(const Vector3&other) const {
00127         return Vector3(x*other.x,y*other.y,z*other.z);
00128     }
00129     Vector3 operator-(const Vector3&other) const {
00130         return Vector3(x-other.x,y-other.y,z-other.z);
00131     }
00132     Vector3 operator-() const {
00133         return Vector3(-x,-y,-z);
00134     }
00135     Vector3& operator*=(scalar scale) {
00136         x*=scale;
00137         y*=scale;
00138         z*=scale;
00139         return *this;
00140     }
00141     Vector3& operator/=(scalar scale) {
00142         x/=scale;
00143         y/=scale;
00144         z/=scale;
00145         return *this;
00146     }
00147     Vector3& operator+=(const Vector3& other) {
00148         x+=other.x;
00149         y+=other.y;
00150         z+=other.z;
00151         return *this;
00152     }
00153     Vector3& operator-=(const Vector3& other) {
00154         x-=other.x;
00155         y-=other.y;
00156         z-=other.z;
00157         return *this;
00158     }
00159     Vector3 cross(const Vector3&other) const {
00160         return Vector3(y*other.z-z*other.y,
00161                        z*other.x-x*other.z,
00162                        x*other.y-y*other.x);
00163     }
00164     scalar dot(const Vector3 &other) const{
00165         return x*other.x+y*other.y+z*other.z;
00166     }
00167     Vector3 min(const Vector3&other)const {
00168         return Vector3(other.x<x?other.x:x,
00169                        other.y<y?other.y:y,
00170                        other.z<z?other.z:z);
00171     }
00172     Vector3 max(const Vector3&other)const {
00173         return Vector3(other.x>x?other.x:x,
00174                        other.y>y?other.y:y,
00175                        other.z>z?other.z:z);
00176     }
00177     scalar lengthSquared()const {
00178         return dot(*this);
00179     }
00180     scalar length()const {
00181         return (scalar)sqrt(dot(*this));
00182     }
00183     bool operator==(const Vector3&other)const {
00184         return x==other.x&&y==other.y&&z==other.z;
00185     }
00186     bool operator!=(const Vector3&other)const {
00187         return x!=other.x||y!=other.y||z!=other.z;
00188     }
00189     Vector3 normal()const {
00190         scalar len=length();
00191         if (len>1e-08)
00192             return *this/len;
00193         return *this;
00194     }
00195     scalar normalizeThis() {
00196         scalar len=length();
00197         if (len>1e-08)
00198             *this/=len;
00199         return len;
00200     }
00201     std::string toString()const {
00202         std::ostringstream os;
00203         os<<'<'<<x<<","<<y<<","<<z<<'>';
00204         return os.str();
00205     }
00206     Vector3 reflect(const Vector3& normal)const {
00207         return Vector3(*this-normal*((scalar)2.0*this->dot(normal)));
00208     }
00209 
00210     size_t hash() const {
00211       size_t seed = 0;
00212       boost::hash_combine(seed, x);
00213       boost::hash_combine(seed, y);
00214       boost::hash_combine(seed, z);
00215       return seed;
00216     }
00217 
00218     class Hasher{public:
00219         size_t operator() (const Vector3 &v) const {
00220             return v.hash();
00221         }
00222     };
00223 };
00224 
00225 template<typename scalar> inline Vector3<scalar> operator *(scalar lhs, const Vector3<scalar> &rhs) {
00226     return Vector3<scalar>(lhs*rhs.x,lhs*rhs.y,lhs*rhs.z);
00227 }
00228 template<typename scalar> inline Vector3<scalar> operator /(scalar lhs, const Vector3<scalar> &rhs) {
00229     return Vector3<scalar>(lhs/rhs.x,lhs/rhs.y,lhs/rhs.z);
00230 }
00231 template<typename scalar> inline std::ostream& operator <<(std::ostream& os, const Vector3<scalar> &rhs) {
00232     os<<'<'<<rhs.x<<","<<rhs.y<<","<<rhs.z<<'>';
00233     return os;
00234 }
00235 template<typename scalar> inline std::istream& operator >>(std::istream& is, Vector3<scalar> &rhs) {
00236     // FIXME this should be more robust.  It currently relies on the exact format provided by operator <<
00237     char dummy;
00238     is >> dummy >> rhs.x >> dummy >> rhs.y >> dummy >> rhs.z >> dummy;
00239     return is;
00240 }
00241 
00242 }
00243 #endif