Sirikata
libcore/include/sirikata/core/util/Vector2.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Vector2.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_VECTOR2_HPP_
00033 #define _SIRIKATA_VECTOR2_HPP_
00034 
00035 #include <string>
00036 #include <cassert>
00037 #include <sstream>
00038 
00039 namespace Sirikata {
00040 template <typename scalar> class Vector2 {
00041 public:
00042     static const unsigned char size = 2;
00043     typedef scalar real;
00044     union {
00045         struct {
00046             scalar x;
00047             scalar y;
00048         };
00049         scalar v[2];
00050     };
00051     Vector2(scalar x, scalar y) {
00052         this->x=x;
00053         this->y=y;
00054     }
00055     template <class V> explicit Vector2(const V&other) {
00056         x=other[0];
00057         y=other[1];
00058     }
00059     Vector2(){}
00060     template <class V> static Vector2 fromSSE(const V&other){
00061         return Vector2(other.x(),other.y());
00062     }
00063     scalar&operator[](const unsigned int i) {
00064         assert(i<2);
00065         return v[i];
00066     }
00067 #if 0
00068     template<class T> operator T() const{
00069         return T(x,y);
00070     }
00071 #else
00072     template<class T> T convert() const{
00073         return T(x,y);
00074     }
00075 #endif
00076     scalar operator[](const unsigned int i) const{
00077         assert(i<2);
00078         return v[i];
00079     }
00080     Vector2&operator=(scalar other) {
00081         x=other;
00082         y=other;
00083         return *this;
00084     }
00085     static Vector2 zero() {
00086         return Vector2(0,0);
00087     }
00088     static Vector2 unitX() {
00089         return Vector2(1,0);
00090     }
00091     static Vector2 unitY() {
00092         return Vector2(0,1);
00093     }
00094     static Vector2 unitNegX() {
00095         return Vector2(-1,0);
00096     }
00097     static Vector2 unitNegY() {
00098         return Vector2(0,-1);
00099     }
00100     Vector2 operator*(scalar scale) const {
00101         return Vector2(x*scale,y*scale);
00102     }
00103     Vector2 operator/(scalar scale) const {
00104         return Vector2(x/scale,y/scale);
00105     }
00106     Vector2 operator+(const Vector2&other) const {
00107         return Vector2(x+other.x,y+other.y);
00108     }
00109     Vector2 componentMultiply(const Vector2&other) const {
00110         return Vector2(x*other.x,y*other.y);
00111     }
00112     Vector2 operator-(const Vector2&other) const {
00113         return Vector2(x-other.x,y-other.y);
00114     }
00115     Vector2 operator-() const {
00116         return Vector2(-x,-y);
00117     }
00118     Vector2& operator*=(scalar scale) {
00119         x*=scale;
00120         y*=scale;
00121         return *this;
00122     }
00123     Vector2& operator/=(scalar scale) {
00124         x/=scale;
00125         y/=scale;
00126         return *this;
00127     }
00128     Vector2& operator+=(const Vector2& other) {
00129         x+=other.x;
00130         y+=other.y;
00131         return *this;
00132     }
00133     Vector2& operator-=(const Vector2& other) {
00134         x-=other.x;
00135         y-=other.y;
00136         return *this;
00137     }
00138     scalar dot(const Vector2 &other) const{
00139         return x*other.x+y*other.y;
00140     }
00141     Vector2 min(const Vector2&other)const {
00142         return Vector2(other.x<x?other.x:x,
00143                        other.y<y?other.y:y);
00144     }
00145     Vector2 max(const Vector2&other)const {
00146         return Vector2(other.x>x?other.x:x,
00147                        other.y>y?other.y:y);
00148     }
00149     scalar lengthSquared()const {
00150         return dot(*this);
00151     }
00152     scalar length()const {
00153         return (scalar)sqrt(dot(*this));
00154     }
00155     bool operator==(const Vector2&other)const {
00156         return x==other.x&&y==other.y;
00157     }
00158     bool operator!=(const Vector2&other)const {
00159         return x!=other.x||y!=other.y;
00160     }
00161     Vector2 normal()const {
00162         scalar len=length();
00163         if (len>1e-08)
00164             return *this/len;
00165         return *this;
00166     }
00167     scalar normalizeThis() {
00168         scalar len=length();
00169         if (len>1e-08)
00170             *this/=len;
00171         return len;
00172     }
00173     std::string toString()const {
00174         std::ostringstream os;
00175         os<<'<'<<x<<","<<y<<'>';
00176         return os.str();
00177     }
00178     Vector2 reflect(const Vector2& normal)const {
00179         return Vector2(*this-normal*((scalar)2.0*this->dot(normal)));
00180     }
00181 };
00182 
00183 template<typename scalar> inline Vector2<scalar> operator *(scalar lhs, const Vector2<scalar> &rhs) {
00184     return Vector2<scalar>(lhs*rhs.x,lhs*rhs.y,lhs*rhs.z);
00185 }
00186 template<typename scalar> inline Vector2<scalar> operator /(scalar lhs, const Vector2<scalar> &rhs) {
00187     return Vector2<scalar>(lhs/rhs.x,lhs/rhs.y);
00188 }
00189 template<typename scalar> inline std::ostream& operator <<(std::ostream& os, const Vector2<scalar> &rhs) {
00190     os<<'<'<<rhs.x<<","<<rhs.y<<","<<'>';
00191     return os;
00192 }
00193 template<typename scalar> inline std::istream& operator >>(std::istream& is, Vector2<scalar> &rhs) {
00194     // FIXME this should be more robust.  It currently relies on the exact format provided by operator <<
00195     char dummy;
00196     is >> dummy >> rhs.x >> dummy >> rhs.y >> dummy;
00197     return is;
00198 }
00199 
00200 }
00201 #endif