Simple Application Framework  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Saf/Math/Algebra/Vector.h
Go to the documentation of this file.
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