Simple Application Framework
1
|
00001 /* 00002 This file is part of Simple Application Framework (Saf) library. 00003 Copyright (C) 2010 - 2012 Ondrej Danek <ondrej.danek@gmail.com> 00004 00005 This library is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published 00007 by the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 Saf is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Simple Application Framework library. If not, 00017 see <http://www.gnu.org/licenses/>. 00018 */ 00019 00028 #ifndef SAF_MATH_ALGEBRA_VECTOR_H 00029 #define SAF_MATH_ALGEBRA_VECTOR_H 00030 00031 #include <math.h> 00032 #include "../../Type.h" 00033 #include "../../Collection/StaticArray.h" 00034 #include "../Basic.h" 00035 #include "../Constant.h" 00036 #include "../Range.h" 00037 #include "../Calculus/Powers.h" 00038 #include "Number.h" 00039 00040 namespace Saf 00041 { 00042 namespace Math 00043 { 00044 // @todo Vektorovy a maticovy operace jako scitani, nasobeni, pricitani skalaru apod. 00045 // udelat jako obecny funkce, ktery berou vstupni a vystupni parametr, at to lze 00046 // pouzivat i na zdedene tridy. Pripadne sem dat jen shortcut methods jako Gcd, Lcm, atd. 00047 00049 namespace Algebra 00050 { 00051 // Forward declaration 00052 template <Size N, Size M, class T> class Matrix; 00053 00059 template <Size N, class T> 00060 class Vector 00061 : public Collection::StaticArray<N,T> 00062 { 00063 protected: 00064 typedef Collection::StaticArray<N,T> BaseType; 00065 typedef Vector<N,T> MyType; 00066 00067 protected: 00068 using BaseType::m_data; 00069 00070 public: 00075 Vector() 00076 {} 00077 00082 explicit Vector(const T& v) 00083 : BaseType(v) 00084 {} 00085 00087 Vector(const T& v1, const T& v2) 00088 : BaseType(v1,v2) 00089 {} 00090 00092 Vector(const T& v1, const T& v2, const T& v3) 00093 : BaseType(v1,v2,v3) 00094 {} 00095 00097 Vector(const T& v1, const T& v2, const T& v3, const T& v4) 00098 : BaseType(v1,v2,v3,v4) 00099 {} 00100 00102 Vector(const MyType& v) 00103 { 00104 *this = v; 00105 } 00106 00108 MyType& operator=(const MyType& v) 00109 { 00110 BaseType::operator=(v); 00111 return *this; 00112 } 00113 00115 MyType& operator+=(const MyType& v) 00116 { 00117 for (Size i = 0; i < N; i++) 00118 { 00119 m_data[i] += v.m_data[i]; 00120 } 00121 00122 return *this; 00123 } 00124 00126 MyType& operator-=(const MyType& v) 00127 { 00128 for (Size i = 0; i < N; i++) 00129 { 00130 m_data[i] -= v.m_data[i]; 00131 } 00132 00133 return *this; 00134 } 00135 00137 MyType& operator*=(const MyType& v) 00138 { 00139 for (Size i = 0; i < N; i++) 00140 { 00141 m_data[i] *= v.m_data[i]; 00142 } 00143 00144 return *this; 00145 } 00146 00148 MyType& operator*=(const T& v) 00149 { 00150 for (Size i = 0; i < N; i++) 00151 { 00152 m_data[i] *= v; 00153 } 00154 00155 return *this; 00156 } 00157 00159 MyType& operator/=(const MyType& v) 00160 { 00161 for (Size i = 0; i < N; i++) 00162 { 00163 m_data[i] /= v.m_data[i]; 00164 } 00165 00166 return *this; 00167 } 00168 00170 MyType& operator/=(const T& v) 00171 { 00172 for (Size i = 0; i < N; i++) 00173 { 00174 m_data[i] /= v; 00175 } 00176 00177 return *this; 00178 } 00179 00181 MyType operator+(const MyType& v) const 00182 { 00183 MyType nv; 00184 00185 for (Size i = 0; i < N; i++) 00186 { 00187 nv.m_data[i] = m_data[i] + v.m_data[i]; 00188 } 00189 00190 return nv; 00191 } 00192 00194 MyType operator-(const MyType& v) const 00195 { 00196 MyType nv; 00197 00198 for (Size i = 0; i < N; i++) 00199 { 00200 nv.m_data[i] = m_data[i] - v.m_data[i]; 00201 } 00202 00203 return nv; 00204 } 00205 00207 MyType operator*(const MyType& v) const 00208 { 00209 MyType nv; 00210 00211 for (Size i = 0; i < N; i++) 00212 { 00213 nv.m_data[i] = m_data[i] * v.m_data[i]; 00214 } 00215 00216 return nv; 00217 } 00218 00220 MyType operator*(const T& v) const 00221 { 00222 MyType nv; 00223 00224 for (Size i = 0; i < N; i++) 00225 { 00226 nv.m_data[i] = m_data[i] * v; 00227 } 00228 00229 return nv; 00230 } 00231 00233 MyType operator/(const MyType &v) const 00234 { 00235 MyType nv; 00236 00237 for (Size i = 0; i < N; i++) 00238 { 00239 nv.m_data[i] = m_data[i] / v.m_data[i]; 00240 } 00241 00242 return nv; 00243 } 00244 00246 MyType operator/(const T& v) const 00247 { 00248 MyType nv; 00249 00250 for (Size i = 0; i < N; i++) 00251 { 00252 nv.m_data[i] = m_data[i] / v; 00253 } 00254 00255 return nv; 00256 } 00257 00259 MyType operator-() const 00260 { 00261 return *this * -1; 00262 } 00263 00265 template <Size M> 00266 Vector<M,T> Mul(const Matrix<N,M,T> &m) const 00267 { 00268 Vector<M,T> v; 00269 00270 for (Size i = 0; i < M; i++) 00271 { 00272 Size p = i; 00273 T sum = 0; 00274 00275 for (Size k = 0; k < N; k++, p += M) 00276 { 00277 sum += m_data[k] * m[p]; 00278 } 00279 00280 v[i] = sum; 00281 } 00282 00283 return v; 00284 } 00285 00290 bool operator<(const MyType& v) const 00291 { 00292 for (Size i = N; i-- > 0; ) 00293 { 00294 if (m_data[i] < v.m_data[i]) 00295 { 00296 return true; 00297 } 00298 else if (m_data[i] > v.m_data[i]) 00299 { 00300 return false; 00301 } 00302 } 00303 00304 return false; 00305 } 00306 00311 bool operator<=(const MyType& v) const 00312 { 00313 for (Size i = N; i-- > 0; ) 00314 { 00315 if (m_data[i] < v.m_data[i]) 00316 { 00317 return true; 00318 } 00319 else if (m_data[i] > v.m_data[i]) 00320 { 00321 return false; 00322 } 00323 } 00324 00325 return true; 00326 } 00327 00329 bool operator>(const MyType& v) const 00330 { 00331 return v < *this; 00332 } 00333 00335 bool operator>=(const MyType& v) const 00336 { 00337 return v <= *this; 00338 } 00339 00341 template <Size M> 00342 Matrix<N,M,T> OuterProduct (const Vector<M,T> &v) 00343 { 00344 Matrix<N,M,T> m; 00345 Size p = 0; 00346 00347 for (Size i = 0; i < N; i++) 00348 { 00349 for (Size j = 0; j < M; j++, p++) 00350 { 00351 m[p] = m_data[i] * v[j]; 00352 } 00353 } 00354 00355 return m; 00356 } 00357 00359 T DotProduct (const MyType& v) const 00360 { 00361 T sum = 0; 00362 00363 for (Size i = 0; i < N; i++) 00364 { 00365 sum += m_data[i] * v.m_data[i]; 00366 } 00367 00368 return sum; 00369 } 00370 00372 template <Size M> 00373 T InnerProduct (const Matrix<N,M,T> &m, const MyType& v) const 00374 { 00375 return Mul(m).DotProduct(v); 00376 } 00377 00379 Matrix<1,N,T> ToRowMatrix() const 00380 { 00381 Matrix<1,N,T> m; 00382 00383 for (Size i = 0; i < N; i++) 00384 { 00385 m[i] = m_data[i]; 00386 } 00387 00388 return m; 00389 } 00390 00392 Matrix<N,1,T> ToColumnMatrix() const 00393 { 00394 Matrix<N,1,T> m; 00395 00396 for (Size i = 0; i < N; i++) 00397 { 00398 m[i] = m_data[i]; 00399 } 00400 00401 return m; 00402 } 00403 00405 T Length() const 00406 { 00407 return Calculus::Sqrt(DotProduct(*this)); 00408 } 00409 00416 T Length(const Matrix<N,N,T> &m) const 00417 { 00418 return Calculus::Sqrt(InnerProduct(m,*this)); 00419 } 00420 00425 T Angle(const MyType& v) const 00426 { 00427 return acos(DotProduct(v) / (Length() * v.Length())); 00428 } 00429 00437 T Angle(const MyType& v, const Matrix<N,N,T>& m) const 00438 { 00439 return acos(InnerProduct(m,v) / (Length(m) * v.Length(m))); 00440 } 00441 00443 MyType& Normalize() 00444 { 00445 T len = Length(); 00446 00447 for (Size i = 0; i < N; i++) 00448 { 00449 m_data[i] /= len; 00450 } 00451 00452 return *this; 00453 } 00454 00456 MyType Normalized() const 00457 { 00458 MyType nv; 00459 T len = Length(); 00460 00461 for (Size i = 0; i < N; i++) 00462 { 00463 nv.m_data[i] = m_data[i] / len; 00464 } 00465 00466 return nv; 00467 } 00468 00474 template <Size CN,class CT> 00475 Vector<CN,CT> Convert(CT padVal = 0) const 00476 { 00477 Vector<CN,CT> n; 00478 00479 if (CN < N) 00480 { 00481 for (Size i = 0; i < CN; i++) 00482 { 00483 n[i] = (CT)m_data[i]; 00484 } 00485 } 00486 else 00487 { 00488 for (Size i = 0; i < N; i++) 00489 { 00490 n[i] = (CT)m_data[i]; 00491 } 00492 for (Size i = N; i < CN; i++) 00493 { 00494 n[i] = padVal; 00495 } 00496 } 00497 00498 return n; 00499 } 00500 00508 Int8 Sgn() const 00509 { 00510 for (Size i = N; i-- > 0; ) 00511 { 00512 if (m_data[i] < 0) 00513 { 00514 return -1; 00515 } 00516 else if (m_data[i] > 0) 00517 { 00518 return 1; 00519 } 00520 } 00521 00522 return 0; 00523 } 00524 00526 00528 MyType& Fill(const T& val) 00529 { 00530 Algo::Range::Fill(this->Begin(), this->End(), val); 00531 return *this; 00532 } 00533 00535 T Sum() const 00536 { 00537 return Math::Range::Sum(this->Begin(), this->End()); 00538 } 00539 00541 T Product() const 00542 { 00543 return Math::Range::Product(this->Begin(), this->End()); 00544 } 00545 00547 T Gcd() const 00548 { 00549 return Algebra::Gcd(this->Begin(), this->End()); 00550 } 00551 00553 T Lcm() const 00554 { 00555 return Algebra::Lcm(this->Begin(), this->End()); 00556 } 00557 }; 00558 00560 template <Size N, class T> 00561 Vector<N,T> operator* (const T& val, const Vector<N,T> &v) 00562 { 00563 return v * val; 00564 } 00565 00567 template <Size N, class T> 00568 Vector<N,T> operator/ (const T& val, const Vector<N,T> &v) 00569 { 00570 Vector<N,T> nv; 00571 00572 for (Size i = 0; i < N; i++) 00573 { 00574 nv[i] = val / v[i]; 00575 } 00576 00577 return nv; 00578 } 00579 00581 template <class T> 00582 Vector<3,T> CrossProduct (const Vector<3,T> &v1, const Vector<3,T> &v2) 00583 { 00584 Vector<3,T> nv; 00585 00586 nv[0] = v1[1] * v2[2] - v1[2] * v2[1]; 00587 nv[1] = v1[2] * v2[0] - v1[0] * v2[2]; 00588 nv[2] = v1[0] * v2[1] - v1[1] * v2[0]; 00589 00590 return nv; 00591 } 00592 00594 template <class T> 00595 T ClockwiseAngle (const Vector<2,T> &v1, const Vector<2,T> &v2) 00596 { 00597 T ang = v1.Angle(v2); 00598 00599 // Check the third coordinate of cross product 00600 if (v1[0] * v2[1] - v1[1] * v2[0] > 0) 00601 { 00602 return 2 * T(Constant::Pi) - ang; 00603 } 00604 00605 return ang; 00606 } 00607 } 00608 } 00609 } 00610 00611 #endif