WFMath
1.0.2
|
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