WFMath  1.0.2
vector.h
00001 // vector.h (Vector<> class definition)
00002 //
00003 //  The WorldForge Project
00004 //  Copyright (C) 2001  The WorldForge Project
00005 //
00006 //  This program is free software; you can redistribute it and/or modify
00007 //  it under the terms of the GNU General Public License as published by
00008 //  the Free Software Foundation; either version 2 of the License, or
00009 //  (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 //
00020 //  For information about WorldForge and its authors, please contact
00021 //  the Worldforge Web Site at http://www.worldforge.org.
00022 
00023 // Author: Ron Steinke
00024 // Created: 2001-12-7
00025 
00026 // Extensive amounts of this material come from the Vector2D
00027 // and Vector3D classes from stage/math, written by Bryce W.
00028 // Harrington, Kosh, and Jari Sundell (Rakshasa).
00029 
00030 #ifndef WFMATH_VECTOR_H
00031 #define WFMATH_VECTOR_H
00032 
00033 #include <wfmath/const.h>
00034 
00035 #include <iosfwd>
00036 
00037 #include <cmath>
00038 
00039 namespace WFMath {
00040 
00041 template<int dim>
00042 Vector<dim>& operator+=(Vector<dim>& v1, const Vector<dim>& v2);
00043 template<int dim>
00044 Vector<dim>& operator-=(Vector<dim>& v1, const Vector<dim>& v2);
00045 template<int dim>
00046 Vector<dim>& operator*=(Vector<dim>& v, CoordType d);
00047 template<int dim>
00048 Vector<dim>& operator/=(Vector<dim>& v, CoordType d);
00049 
00050 template<int dim>
00051 Vector<dim> operator+(const Vector<dim>& v1, const Vector<dim>& v2);
00052 template<int dim>
00053 Vector<dim> operator-(const Vector<dim>& v1, const Vector<dim>& v2);
00054 template<int dim>
00055 Vector<dim> operator-(const Vector<dim>& v); // Unary minus
00056 template<int dim>
00057 Vector<dim> operator*(CoordType d, const Vector<dim>& v);
00058 template<int dim>
00059 Vector<dim> operator*(const Vector<dim>& v, CoordType d);
00060 template<int dim>
00061 Vector<dim> operator/(const Vector<dim>& v, CoordType d);
00062 
00063 template<int dim>
00064 CoordType Dot(const Vector<dim>& v1, const Vector<dim>& v2);
00065 
00066 template<int dim>
00067 CoordType Angle(const Vector<dim>& v, const Vector<dim>& u);
00068 
00069 // The following are defined in rotmatrix_funcs.h
00071 template<int dim> // m * v
00072 Vector<dim> Prod(const RotMatrix<dim>& m, const Vector<dim>& v);
00074 template<int dim> // m^-1 * v
00075 Vector<dim> InvProd(const RotMatrix<dim>& m, const Vector<dim>& v);
00077 
00080 template<int dim> // v * m
00081 Vector<dim> Prod(const Vector<dim>& v, const RotMatrix<dim>& m);
00083 template<int dim> // v * m^-1
00084 Vector<dim> ProdInv(const Vector<dim>& v, const RotMatrix<dim>& m);
00085 
00087 template<int dim>
00088 Vector<dim> operator*(const RotMatrix<dim>& m, const Vector<dim>& v);
00090 template<int dim>
00091 Vector<dim> operator*(const Vector<dim>& v, const RotMatrix<dim>& m);
00092 
00093 template<int dim>
00094 Vector<dim> operator-(const Point<dim>& c1, const Point<dim>& c2);
00095 template<int dim>
00096 Point<dim> operator+(const Point<dim>& c, const Vector<dim>& v);
00097 template<int dim>
00098 Point<dim> operator-(const Point<dim>& c, const Vector<dim>& v);
00099 template<int dim>
00100 Point<dim> operator+(const Vector<dim>& v, const Point<dim>& c);
00101 
00102 template<int dim>
00103 Point<dim>& operator+=(Point<dim>& p, const Vector<dim>& v);
00104 template<int dim>
00105 Point<dim>& operator-=(Point<dim>& p, const Vector<dim>& v);
00106 
00107 template<int dim>
00108 std::ostream& operator<<(std::ostream& os, const Vector<dim>& v);
00109 template<int dim>
00110 std::istream& operator>>(std::istream& is, Vector<dim>& v);
00111 
00112 template<typename Shape>
00113 class ZeroPrimitive;
00114 
00116 
00120 template<int dim = 3>
00121 class Vector {
00122  friend class ZeroPrimitive<Vector<dim> >;
00123  public:
00125   Vector() : m_valid(false) {}
00127   Vector(const Vector& v);
00129   explicit Vector(const AtlasInType& a);
00131   explicit Vector(const Point<dim>& point);
00132 
00136   static const Vector<dim>& ZERO();
00137   
00138   friend std::ostream& operator<< <dim>(std::ostream& os, const Vector& v);
00139   friend std::istream& operator>> <dim>(std::istream& is, Vector& v);
00140 
00142   AtlasOutType toAtlas() const;
00144   void fromAtlas(const AtlasInType& a);
00145 
00146   Vector& operator=(const Vector& v);
00147 
00148   bool isEqualTo(const Vector& v, CoordType epsilon = numeric_constants<CoordType>::epsilon()) const;
00149   bool operator==(const Vector& v) const {return isEqualTo(v);}
00150   bool operator!=(const Vector& v) const {return !isEqualTo(v);}
00151 
00152   bool isValid() const {return m_valid;}
00154   void setValid(bool valid = true) {m_valid = valid;}
00155 
00157   Vector& zero();
00158 
00159   // Math operators
00160 
00162   friend Vector& operator+=<dim>(Vector& v1, const Vector& v2);
00164   friend Vector& operator-=<dim>(Vector& v1, const Vector& v2);
00166   friend Vector& operator*=<dim>(Vector& v, CoordType d);
00168   friend Vector& operator/=<dim>(Vector& v, CoordType d);
00169 
00171   friend Vector operator+<dim>(const Vector& v1, const Vector& v2);
00173   friend Vector operator-<dim>(const Vector& v1, const Vector& v2);
00175   friend Vector operator-<dim>(const Vector& v); // Unary minus
00177   friend Vector operator*<dim>(CoordType d, const Vector& v);
00179   friend Vector operator*<dim>(const Vector& v, CoordType d);
00181   friend Vector operator/<dim>(const Vector& v, CoordType d);
00182 
00183   // documented outside the class definition
00184   friend Vector Prod<dim>(const RotMatrix<dim>& m, const Vector& v);
00185   friend Vector InvProd<dim>(const RotMatrix<dim>& m, const Vector& v);
00186 
00188   CoordType operator[](const int i) const {return m_elem[i];}
00190   CoordType& operator[](const int i)      {return m_elem[i];}
00191 
00193   friend Vector operator-<dim>(const Point<dim>& c1, const Point<dim>& c2);
00195   friend Point<dim> operator+<dim>(const Point<dim>& c, const Vector& v);
00197   friend Point<dim> operator-<dim>(const Point<dim>& c, const Vector& v);
00199   friend Point<dim> operator+<dim>(const Vector& v, const Point<dim>& c);
00200 
00202   friend Point<dim>& operator+=<dim>(Point<dim>& p, const Vector& rhs);
00204   friend Point<dim>& operator-=<dim>(Point<dim>& p, const Vector& rhs);
00205 
00206   friend CoordType Cross(const Vector<2>& v1, const Vector<2>& v2);
00207   friend Vector<3> Cross(const Vector<3>& v1, const Vector<3>& v2);
00208 
00210   friend CoordType Dot<dim>(const Vector& v1, const Vector& v2);
00212   friend CoordType Angle<dim>(const Vector& v, const Vector& u);
00213 
00215   CoordType sqrMag() const;
00217   CoordType mag() const         {return std::sqrt(sqrMag());}
00219   Vector& normalize(CoordType norm = 1.0)
00220   {CoordType themag = mag(); return (*this *= norm / themag);}
00221 
00223 
00234   CoordType sloppyMag() const;
00236 
00241   Vector& sloppyNorm(CoordType norm = 1.0);
00242 
00243   // Can't seem to implement these as constants, implementing
00244   // inline lookup functions instead.
00246   static CoordType sloppyMagMax();
00248 
00254   static CoordType sloppyMagMaxSqrt();
00255 
00257   Vector& rotate(int axis1, int axis2, CoordType theta);
00258 
00260 
00263   Vector& rotate(const Vector& v1, const Vector& v2, CoordType theta);
00264 
00266   Vector& rotate(const RotMatrix<dim>&);
00267 
00268   // mirror image functions
00269 
00271   Vector& mirror(const int i) { m_elem[i] *= -1; return *this;}
00273   Vector& mirror(const Vector& v)
00274   {return operator-=(*this, 2 * v * Dot(v, *this) / v.sqrMag());}
00276 
00279   Vector& mirror()              {return operator*=(*this, -1);}
00280 
00281   // Specialized 2D/3D stuff starts here
00282 
00283   // The following functions are defined only for
00284   // two dimensional (rotate(CoordType), Vector<>(CoordType, CoordType))
00285   // and three dimensional (the rest of them) vectors.
00286   // Attempting to call these on any other vector will
00287   // result in a linker error.
00288 
00290   Vector(CoordType x, CoordType y);
00292   Vector(CoordType x, CoordType y, CoordType z);
00293 
00295   Vector& rotate(CoordType theta);
00296 
00298   Vector& rotateX(CoordType theta);
00300   Vector& rotateY(CoordType theta);
00302   Vector& rotateZ(CoordType theta);
00303 
00305   Vector& rotate(const Vector& axis, CoordType theta);
00307   Vector& rotate(const Quaternion& q);
00308 
00309   // Label the first three components of the vector as (x,y,z) for
00310   // 2D/3D convienience
00311 
00313   CoordType x() const   {return m_elem[0];}
00315   CoordType& x()        {return m_elem[0];}
00317   CoordType y() const   {return m_elem[1];}
00319   CoordType& y()        {return m_elem[1];}
00321   CoordType z() const;
00323   CoordType& z();
00324 
00326   Vector& mirrorX()     {return mirror(0);}
00328   Vector& mirrorY()     {return mirror(1);}
00330   Vector& mirrorZ();
00331 
00333   Vector& polar(CoordType r, CoordType theta);
00335   void asPolar(CoordType& r, CoordType& theta) const;
00336 
00338   Vector& polar(CoordType r, CoordType theta, CoordType z);
00340   void asPolar(CoordType& r, CoordType& theta, CoordType& z) const;
00342   Vector& spherical(CoordType r, CoordType theta, CoordType phi);
00344   void asSpherical(CoordType& r, CoordType& theta, CoordType& phi) const;
00345 
00346   const CoordType* elements() const {return m_elem;}
00347 
00348  private:
00349   double _scaleEpsilon(const Vector& v, CoordType epsilon = numeric_constants<CoordType>::epsilon()) const
00350   {return _ScaleEpsilon(m_elem, v.m_elem, dim, epsilon);}
00351 
00352   CoordType m_elem[dim];
00353   bool m_valid;
00354 };
00355 
00356 template<>
00357 inline CoordType Vector<3>::z() const
00358 {
00359   return m_elem[2];
00360 }
00361 
00362 template<>
00363 inline CoordType& Vector<3>::z()
00364 {
00365   return m_elem[2];
00366 }
00367 
00368 template<>
00369 inline Vector<3>& Vector<3>::mirrorZ()
00370 {
00371   return mirror(2);
00372 }
00373 
00375 CoordType Cross(const Vector<2>& v1, const Vector<2>& v2);
00377 Vector<3> Cross(const Vector<3>& v1, const Vector<3>& v2);
00378 
00380 
00385 template<int dim>
00386 bool Parallel(const Vector<dim>& v1, const Vector<dim>& v2, bool& same_dir);
00387 
00389 
00392 template<int dim>
00393 bool Parallel(const Vector<dim>& v1, const Vector<dim>& v2);
00394 
00396 template<int dim>
00397 bool Perpendicular(const Vector<dim>& v1, const Vector<dim>& v2);
00398 
00399 template <int dim>
00400 inline Vector<dim> operator+(const Vector<dim>& v1, const Vector<dim>& v2)
00401 {
00402   Vector<dim> ans(v1);
00403 
00404   ans += v2;
00405 
00406   return ans;
00407 }
00408 
00409 template <int dim>
00410 inline Vector<dim> operator-(const Vector<dim>& v1, const Vector<dim>& v2)
00411 {
00412   Vector<dim> ans(v1);
00413 
00414   ans -= v2;
00415 
00416   return ans;
00417 }
00418 
00419 template <int dim>
00420 inline Vector<dim> operator*(const Vector<dim>& v, CoordType d)
00421 {
00422   Vector<dim> ans(v);
00423 
00424   ans *= d;
00425 
00426   return ans;
00427 }
00428 
00429 template<int dim>
00430 inline Vector<dim> operator*(CoordType d, const Vector<dim>& v)
00431 {
00432   Vector<dim> ans(v);
00433 
00434   ans *= d;
00435 
00436   return ans;
00437 }
00438 
00439 template <int dim>
00440 inline Vector<dim> operator/(const Vector<dim>& v, CoordType d)
00441 {
00442   Vector<dim> ans(v);
00443 
00444   ans /= d;
00445 
00446   return ans;
00447 }
00448 
00449 template<int dim>
00450 inline bool Parallel(const Vector<dim>& v1,
00451                      const Vector<dim>& v2,
00452                      bool& same_dir)
00453 {
00454   CoordType dot = Dot(v1, v2);
00455 
00456   same_dir = (dot > 0);
00457 
00458   return Equal(dot * dot, v1.sqrMag() * v2.sqrMag());
00459 }
00460 
00461 template<int dim>
00462 inline bool Parallel(const Vector<dim>& v1, const Vector<dim>& v2)
00463 {
00464   bool same_dir;
00465 
00466   return Parallel(v1, v2, same_dir);
00467 }
00468 
00469 template<>
00470 inline CoordType Vector<1>::sloppyMagMax()
00471 {
00472   return 1.f;
00473 }
00474 
00475 template<>
00476 inline CoordType Vector<2>::sloppyMagMax()
00477 {
00478   return 1.082392200292393968799446410733f;
00479 }
00480 
00481 template<>
00482 inline CoordType Vector<3>::sloppyMagMax()
00483 {
00484   return 1.145934719303161490541433900265f;
00485 }
00486 
00487 template<>
00488 inline CoordType Vector<1>::sloppyMagMaxSqrt()
00489 {
00490   return 1.f;
00491 }
00492 
00493 template<>
00494 inline CoordType Vector<2>::sloppyMagMaxSqrt()
00495 {
00496   return 1.040380795811030899095785063701f;
00497 }
00498 
00499 template<>
00500 inline CoordType Vector<3>::sloppyMagMaxSqrt()
00501 {
00502   return 1.070483404496847625250328653179f;
00503 }
00504 
00505 } // namespace WFMath
00506 
00507 #endif // WFMATH_VECTOR_H