Vec.h

00001 // ----------------------------------------------------------------------------
00002 //
00003 // tagGame - Example code from the book:
00004 //
00005 //           Artficial Intelligence for Computer Games: An Introduction
00006 //           by John David Funge
00007 //
00008 //           www.ai4games.org
00009 //
00010 // Source code distributed under the Copyright (c) 2003-2007, John David Funge
00011 // Original author: John David Funge (www.jfunge.com)
00012 //
00013 // Licensed under the Academic Free License version 3.0 
00014 // (for details see LICENSE.txt in this directory).
00015 //
00016 // ----------------------------------------------------------------------------
00017 
00018 #ifndef TG_VEC_H
00019 #define TG_VEC_H
00020 
00021 #include "MathUtil.h"
00022 
00023 #include <vector>
00024 #include <algorithm>
00025 #include <functional>
00026 #include <numeric>
00027 
00028 namespace tagGame
00029 {
00046    template <class T>
00047    class Vec : public std::vector<T>
00048    {
00049    public:
00050       Vec(size_t const n = 0);
00051       Vec(std::vector<T> const& data);
00052       Vec(Vec const& v);
00053       // ~Vec();
00054 
00055       bool isAlmostEq(Vec const& v) const;
00056       bool isAlmostZero() const;
00057 
00058       std::ostream& output(std::ostream& out) const;
00059 
00060       Vec& set(T const x);
00061       Vec& add(Vec const& v);
00062       Vec& subtract(Vec const& v);
00063       Vec& scale(T const x);
00064       Vec& scale(Vec const& v);
00065 
00066       T length() const;
00067       T squaredLength() const;
00068       T minElement() const;
00069       T maxElement() const;
00070       size_t argMax() const;
00071       size_t argMin() const;
00072       T dot(Vec const& v) const;
00073       T sum() const;
00074 
00075       Vec& normalize();
00076       Vec& setLength(T const x);
00077       Vec& clampMaxLength(T const x);
00078       Vec& shuffle();
00079       Vec& randomize();
00080       Vec& wrap(Vec const& v);
00081       Vec& clamp(Vec const& lower, Vec const& upper);
00082 
00084       Vec& probabilityDistribution();
00085 
00087       Vec relativeTo(Vec const& v) const;
00088    protected:
00089    private:
00090    };
00091 
00092    template <class T>
00093    std::ostream& operator<<(std::ostream& out, Vec<T> const& v);
00094 
00095    typedef Vec<int> IntVec;
00096    typedef Vec<Real> RealVec;
00097 
00098    template <class T>
00099    Vec<T>::Vec(size_t const size) :
00100       std::vector<T>(size)
00101    {
00102       set(T(0));
00103    }
00104    
00105    template <class T>
00106    Vec<T>::Vec(std::vector<T> const& data) :
00107       std::vector<T>(data)
00108    {
00109    }
00110    
00111    template <class T>
00112    Vec<T>::Vec(Vec const& v) :
00113       std::vector<T>(v) 
00114    {
00115    }
00116    
00117    // not really needed, but uncommenting this destructor causes an internal compiler error on MacOSX!
00118    /*
00119    template <class T>
00120    Vec<T>::~Vec()
00121    {
00122       std::vector<T>::~vector<T>();
00123    }
00124    */
00125    
00126    template <class T>
00127    Vec<T>& Vec<T>::set(T const x)
00128    {
00129       fill(std::vector<T>::begin(), std::vector<T>::end(), x);
00130    
00131       return *this;
00132    }
00133    
00134    template <class T>
00135    Vec<T>& Vec<T>::add(Vec const& v)
00136    {
00137       TG_ASSERT(std::vector<T>::size() == v.size());
00138    
00139       transform(std::vector<T>::begin(), std::vector<T>::end(), v.begin(), std::vector<T>::begin(), std::plus<T>());
00140    
00141       return *this;
00142    }
00143    
00144    template <class T>
00145    Vec<T>& Vec<T>::subtract(Vec const& v)
00146    {
00147       TG_ASSERT(std::vector<T>::size() == v.size());
00148    
00149       transform(std::vector<T>::begin(), std::vector<T>::end(), v.begin(), std::vector<T>::begin(), std::minus<T>());
00150    
00151       return *this;
00152    }
00153    
00154    template <class T>
00155    Vec<T>& Vec<T>::scale(T const x)
00156    {
00157       transform(std::vector<T>::begin(), std::vector<T>::end(), std::vector<T>::begin(), std::bind1st(std::multiplies<T>(), x));
00158    
00159       return *this;
00160    }
00161    
00162    template <class T>
00163    Vec<T>& Vec<T>::scale(Vec const& v)
00164    {
00165       transform(std::vector<T>::begin(), std::vector<T>::end(), v.begin(), std::vector<T>::begin(), std::multiplies<T>());
00166    
00167       return *this;
00168    }
00169    
00170    template <class T>
00171    T Vec<T>::length() const
00172    {
00173       return T(sqrt(Real(this->squaredLength())));
00174    }
00175    
00176    template <class T>
00177    T Vec<T>::squaredLength() const
00178    {
00179       return this->dot(*this);
00180    }
00181    
00182    template <class T>
00183    T Vec<T>::dot(Vec const& v) const
00184    {
00185       return inner_product(std::vector<T>::begin(), std::vector<T>::end(), v.begin(), T(0));
00186    }
00187    
00188    template <class T>
00189    class adder : public std::unary_function<T, void>
00190    {
00191    public:
00192       adder() :
00193          sum(T(0))
00194       {
00195       }
00196    
00197       T sum;
00198    
00199       void operator()(T const x)
00200       {
00201         sum += x;
00202       }
00203    };
00204    
00205    template <class T>
00206    T Vec<T>::sum() const
00207    {
00208       return for_each(std::vector<T>::begin(), std::vector<T>::end(), adder<T>()).sum;
00209    }
00210    
00211    template <class T>
00212    size_t Vec<T>::argMin() const
00213    {
00214       return min_element(std::vector<T>::begin(), std::vector<T>::end()) - std::vector<T>::begin();
00215    }
00216    
00217    template <class T>
00218    size_t Vec<T>::argMax() const
00219    {
00220       return max_element(std::vector<T>::begin(), std::vector<T>::end()) - std::vector<T>::begin();
00221    }
00222    
00223    template <class T>
00224    T Vec<T>::minElement() const
00225    {
00226       return (*this)[argMin()];
00227    }
00228    
00229    template <class T>
00230    T Vec<T>::maxElement() const
00231    {
00232       return (*this)[argMax()];
00233    }
00234    
00235    template <class T>
00236    Vec<T>& Vec<T>::normalize()
00237    {
00238       return setLength(T(1));
00239    }
00240    
00241    template <class T>
00242    Vec<T>& Vec<T>::clampMaxLength(T const x)
00243    {
00244       Real const l(length());
00245    
00246       if (x < l)
00247       {
00248          setLength(x);
00249       }
00250    
00251       return *this;
00252    }
00253    
00254    template <class T>
00255    Vec<T>& Vec<T>::setLength(T const x)
00256    {
00257       Real const l(length());
00258       if (MathUtil::isAlmostZero(l))
00259       {
00260          set(T(0));
00261       }
00262       else
00263       {
00264          scale(x/T(l));
00265       }
00266    
00267       return *this;
00268    }
00269    
00270    template <class T>
00271    Vec<T>& Vec<T>::shuffle()
00272    {
00273       // gcc 4 complains if you just try to pass in the reference directly.
00274       std::pointer_to_unary_function<int, int> p(MathUtil::uniform);
00275    
00276       std::random_shuffle(std::vector<T>::begin(), std::vector<T>::end(), p);
00277    
00278       return *this;
00279    }
00280    
00281    template <class T>
00282    Vec<T>& Vec<T>::randomize()
00283    {
00284       generate(std::vector<T>::begin(), std::vector<T>::end(), MathUtil::uniform01);
00285    
00286       return *this;
00287    }
00288    
00289    template <class T>
00290    Vec<T>& Vec<T>::wrap(Vec<T> const& v)
00291    {
00292       TG_ASSERT(std::vector<T>::size() == v.size());
00293    
00294       for (size_t i = 0; i < std::vector<T>::size(); i++)
00295       {
00296          // otherwise loops forever
00297          TG_ASSERT(0 < v[i]);
00298    
00299          while ((*this)[i] < 0)
00300          {
00301             (*this)[i] += v[i];
00302          }
00303          while (v[i] < (*this)[i])
00304          {
00305             (*this)[i] -= v[i];
00306          }
00307       }
00308    
00309       return *this;
00310    }
00311    
00312    template <class T>
00313    Vec<T>& Vec<T>::clamp(Vec<T> const& lower, Vec<T> const& upper)
00314    {
00315       for (size_t i = 0; i < std::vector<T>::size(); i++)
00316       {
00317          (*this)[i] = MathUtil::clamp((*this)[i], lower[i], upper[i]);
00318       }
00319    
00320       return *this;
00321    }
00322    
00323    template<class T>
00324    bool Vec<T>::isAlmostZero() const
00325    {
00326       for (size_t i = 0; i < std::vector<T>::size(); i++)
00327       {
00328          if (!MathUtil::isAlmostZero((*this)[i])) { return false; }
00329       }
00330       return true;
00331    }
00332    
00333    template<class T>
00334    Vec<T> Vec<T>::relativeTo(Vec<T> const& v) const
00335    {
00336       Vec<T> u(*this);
00337    
00338       return u.subtract(v);
00339    }
00340    
00341    template<class T>
00342    std::ostream& Vec<T>::output(std::ostream& out) const
00343    {
00344       copy(std::vector<T>::begin(), std::vector<T>::end(), std::ostream_iterator<T>(out, " "));
00345    
00346       return out;
00347    }
00348 
00349    template <class T>
00350    Vec<T>& Vec<T>::probabilityDistribution()
00351    {
00352       Real const s(sum());
00353 
00354       Util::warn(0 < s, "Vec::probabilityDistribution: vector is zero");
00355 
00356       return scale(Real(1.0)/s);
00357    }
00358    
00359    template <class T>
00360    std::ostream& operator<<(std::ostream& out, Vec<T> const& v)
00361    {
00362       return v.output(out);
00363    }
00364 }
00365 
00366 #endif

Generated on Sat Mar 31 22:30:54 2007 for tagGame by  doxygen 1.5.1