//! \~\file pimathvector.h //! \~\ingroup Math //! \~\brief //! \~english Math vector //! \~russian Математический вектор /* PIP - Platform Independent Primitives Math vector Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIMATHVECTOR_H #define PIMATHVECTOR_H #include "pimathbase.h" #include "pimathcomplex.h" template class PIMathMatrixT; #define PIMATHVECTOR_ZERO_CMP (1E-100) /// Vector templated #define PIMV_FOR for (uint i = 0; i < Size; ++i) //! \~\ingroup Math //! \~\brief //! \~english Fixed-size mathematical vector with compile-time size //! \~russian Вектор математический фиксированного размера с размером во время компиляции //! \details //! \~english Provides vector operations including arithmetic, normalization, angles, cross product, and dot product //! \~russian Предоставляет операции вектора включая арифметику, нормализацию, углы, векторное произведение и скалярное произведение //! \tparam Size The fixed size of the vector //! \tparam Type The element type (arithmetic or complex) template class PIP_EXPORT PIMathVectorT { typedef PIMathVectorT _CVector; static_assert(std::is_arithmetic::value || is_complex::value, "Type must be arithmetic or complex"); static_assert(Size > 0, "Size must be > 0"); public: //! \~english Constructs a vector and fills every coordinate with \a v. //! \~russian Создает вектор и заполняет все координаты значением \a v. PIMathVectorT(const Type & v = Type()) { PIMV_FOR c[i] = v; } //! \~english Constructs a fixed-size vector from a dynamic one of the same size. //! \~russian Создает вектор фиксированного размера из динамического вектора той же длины. PIMathVectorT(const PIVector & val) { assert(Size == val.size()); PIMV_FOR c[i] = val[i]; } //! \~english Constructs a vector from an initializer list with exactly \a Size elements. //! \~russian Создает вектор из списка инициализации ровно с \a Size элементами. PIMathVectorT(std::initializer_list init_list) { assert(Size == init_list.size()); PIMV_FOR c[i] = init_list.begin()[i]; } //! \~english Builds the displacement vector from point \a st to point \a fn. //! \~russian Строит вектор смещения от точки \a st к точке \a fn. static _CVector fromTwoPoints(const _CVector & st, const _CVector & fn) { _CVector tv; PIMV_FOR tv[i] = fn[i] - st[i]; return tv; } //! \~english Returns the compile-time vector dimension. //! \~russian Возвращает размерность вектора, заданную во время компиляции. constexpr uint size() const { return Size; } //! \~english Fills all coordinates with \a v. //! \~russian Заполняет все координаты значением \a v. _CVector & fill(const Type & v) { PIMV_FOR c[i] = v; return *this; } //! \~english Adds \a v to every coordinate. //! \~russian Прибавляет \a v к каждой координате. _CVector & move(const Type & v) { PIMV_FOR c[i] += v; return *this; } //! \~english Adds another vector component-wise. //! \~russian Прибавляет другой вектор покомпонентно. _CVector & move(const _CVector & v) { PIMV_FOR c[i] += v[i]; return *this; } //! \~english Swaps two coordinates in place. //! \~russian Меняет местами две координаты. _CVector & swapElements(uint f, uint s) { piSwap(c[f], c[s]); return *this; } //! \~english Returns the squared Euclidean length. //! \~russian Возвращает квадрат евклидовой длины. Type lengthSqr() const { Type tv(0); PIMV_FOR tv += c[i] * c[i]; return tv; } //! \~english Returns the Euclidean length. Available for arithmetic element types. //! \~russian Возвращает евклидову длину. Доступно для арифметических типов элементов. Type length() const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) return std::sqrt(lengthSqr()); // if (is_complex::value) return 1000.; // std::sqrt(lengthSqr()); } //! \~english Returns the Manhattan length. Available for arithmetic element types. //! \~russian Возвращает манхэттенскую длину. Доступно для арифметических типов элементов. Type manhattanLength() const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { Type tv(0); PIMV_FOR tv += piAbs(c[i]); return tv; } } //! \~english Returns the cosine of the angle to \a v. //! \~russian Возвращает косинус угла к вектору \a v. Type angleCos(const _CVector & v) const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { Type tv = v.length() * length(); assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); return dot(v) / tv; } } //! \~english Returns the sine of the angle to \a v. //! \~russian Возвращает синус угла к вектору \a v. Type angleSin(const _CVector & v) const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { Type tv = angleCos(v); return std::sqrt(Type(1) - tv * tv); } } //! \~english Returns the angle to \a v in radians. //! \~russian Возвращает угол к вектору \a v в радианах. Type angleRad(const _CVector & v) const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { return std::acos(angleCos(v)); } } //! \~english Returns the angle to \a v in degrees. //! \~russian Возвращает угол к вектору \a v в градусах. Type angleDeg(const _CVector & v) const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { return toDeg(angleRad(v)); } } //! \~english Returns the elevation angle from this point to \a v in degrees. //! \~russian Возвращает угол возвышения от этой точки к \a v в градусах. Type angleElevation(const _CVector & v) const { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { return 90.0 - angleDeg(v - *this); } } //! \~english Returns the projection of this vector onto \a v. //! \~russian Возвращает проекцию этого вектора на \a v. _CVector projection(const _CVector & v) { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { Type tv = v.length(); assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); return v * (dot(v) / tv); } } //! \~english Normalizes this vector in place. //! \~russian Нормализует этот вектор на месте. _CVector & normalize() { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { Type tv = length(); assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); if (tv == Type(1)) return *this; PIMV_FOR c[i] /= tv; return *this; } } //! \~english Returns a normalized copy of this vector. //! \~russian Возвращает нормализованную копию этого вектора. _CVector normalized() { _CVector tv(*this); tv.normalize(); return tv; } //! \~english Returns true when all coordinates are zero. //! \~russian Возвращает true, если все координаты равны нулю. bool isNull() const { PIMV_FOR if (c[i] != Type{}) return false; return true; } //! \~english Returns true when this vector is orthogonal to \a v. //! \~russian Возвращает true, если этот вектор ортогонален \a v. bool isOrtho(const _CVector & v) const { return ((*this) ^ v) == Type{}; } //! \~english Returns writable access to a coordinate. //! \~russian Возвращает доступ на запись к координате. Type & operator[](uint index) { return c[index]; } //! \~english Returns read-only access to a coordinate. //! \~russian Возвращает доступ только для чтения к координате. const Type & operator[](uint index) const { return c[index]; } //! \~english Returns a coordinate by value. //! \~russian Возвращает координату по значению. Type at(uint index) const { return c[index]; } //! \~english Returns writable access to a coordinate. //! \~russian Возвращает доступ на запись к координате. inline Type & element(uint index) { return c[index]; } //! \~english Returns read-only access to a coordinate. //! \~russian Возвращает доступ только для чтения к координате. inline const Type & element(uint index) const { return c[index]; } //! \~english Assigns the same value to all coordinates. //! \~russian Присваивает всем координатам одно и то же значение. _CVector & operator=(const Type & v) { PIMV_FOR c[i] = v; return *this; } //! \~english Compares two vectors component-wise. //! \~russian Сравнивает два вектора покомпонентно. bool operator==(const _CVector & v) const { PIMV_FOR if (c[i] != v[i]) return false; return true; } //! \~english Returns true when vectors differ in at least one coordinate. //! \~russian Возвращает true, если векторы различаются хотя бы по одной координате. bool operator!=(const _CVector & v) const { return !(*this == c); } //! \~english Adds \a v component-wise. //! \~russian Прибавляет \a v покомпонентно. void operator+=(const _CVector & v) { PIMV_FOR c[i] += v[i]; } //! \~english Subtracts \a v component-wise. //! \~russian Вычитает \a v покомпонентно. void operator-=(const _CVector & v) { PIMV_FOR c[i] -= v[i]; } //! \~english Multiplies all coordinates by \a v. //! \~russian Умножает все координаты на \a v. void operator*=(const Type & v) { PIMV_FOR c[i] *= v; } //! \~english Divides all coordinates by \a v. //! \~russian Делит все координаты на \a v. void operator/=(const Type & v) { assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); PIMV_FOR c[i] /= v; } //! \~english Returns the vector with inverted sign. //! \~russian Возвращает вектор с противоположным знаком. _CVector operator-() const { _CVector tv; PIMV_FOR tv[i] = -c[i]; return tv; } //! \~english Returns the component-wise sum with \a v. //! \~russian Возвращает покомпонентную сумму с \a v. _CVector operator+(const _CVector & v) const { _CVector tv(*this); PIMV_FOR tv[i] += v[i]; return tv; } //! \~english Returns the component-wise difference with \a v. //! \~russian Возвращает покомпонентную разность с \a v. _CVector operator-(const _CVector & v) const { _CVector tv(*this); PIMV_FOR tv[i] -= v[i]; return tv; } //! \~english Returns a copy scaled by \a v. //! \~russian Возвращает копию, масштабированную на \a v. _CVector operator*(const Type & v) const { _CVector tv(*this); PIMV_FOR tv[i] *= v; return tv; } //! \~english Returns a copy divided by \a v. //! \~russian Возвращает копию, поделенную на \a v. _CVector operator/(const Type & v) const { assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); _CVector tv = _CVector(*this); PIMV_FOR tv[i] /= v; return tv; } //! \~english Returns the 3D cross product with \a v. //! \~russian Возвращает 3D-векторное произведение с \a v. _CVector cross(const _CVector & v) const { static_assert(Size == 3, "cross product avalible only for 3D vectors"); _CVector tv; tv[0] = c[1] * v[2] - v[1] * c[2]; tv[1] = v[0] * c[2] - c[0] * v[2]; tv[2] = c[0] * v[1] - v[0] * c[1]; return tv; } //! \~english Returns the scalar product with \a v. //! \~russian Возвращает скалярное произведение с \a v. Type dot(const _CVector & v) const { Type tv{}; PIMV_FOR tv += c[i] * v[i]; return tv; } //! \~english Returns the component-wise product with \a v. //! \~russian Возвращает покомпонентное произведение с \a v. _CVector mul(const _CVector & v) const { _CVector tv(*this); PIMV_FOR tv[i] *= v[i]; return tv; } //! \~english Returns a copy scaled by \a v. //! \~russian Возвращает копию, масштабированную на \a v. _CVector mul(const Type & v) const { return (*this) * v; } //! \~english Returns the component-wise division by \a v. //! \~russian Возвращает покомпонентное деление на \a v. _CVector div(const _CVector & v) const { _CVector tv(*this); PIMV_FOR { assert(std::abs(v[i]) > PIMATHVECTOR_ZERO_CMP); tv[i] /= v[i]; } return tv; } //! \~english Returns a copy divided by \a v. //! \~russian Возвращает копию, поделенную на \a v. _CVector div(const Type & v) const { return (*this) / v; } //! \~english Returns the vector as a 1 x Size matrix. //! \~russian Возвращает вектор как матрицу 1 x Size. PIMathMatrixT<1, Size, Type> transposed() const { PIMathMatrixT<1, Size, Type> ret; PIMV_FOR ret[0][i] = c[i]; return ret; } //! \~english Returns the distance from this 2D point to the line through \a lp0 and \a lp1. //! \~russian Возвращает расстояние от этой 2D-точки до прямой через \a lp0 и \a lp1. Type distToLine(const _CVector & lp0, const _CVector & lp1) { static_assert(std::is_arithmetic::value, "Unavailable for complex"); if (std::is_arithmetic::value) { _CVector a(lp0, lp1); Type tv = a.length(); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); _CVector b(lp0, *this); return piAbs(a[0] * b[1] - a[1] * b[0]) / tv; } } //! \~english Converts this vector to another dimension and element type. //! \~russian Преобразует этот вектор к другой размерности и типу элементов. template PIMathVectorT turnTo() const { PIMathVectorT tv; uint sz = piMin(Size, Size1); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv; } //! \~english Returns this vector with another element type. //! \~russian Возвращает этот вектор с другим типом элементов. template PIMathVectorT toType() const { PIMathVectorT ret; PIMV_FOR ret[i] = element(i); return ret; } //! \~english Returns a subvector starting at \a offset and zero-fills coordinates outside the source range. //! \~russian Возвращает подвектор, начиная с \a offset, и заполняет нулями координаты вне исходного диапазона. template PIMathVectorT subvector(int offset = 0) const { PIMathVectorT ret; for (int i = 0; i < (int)SubSize; ++i) { int si = i + offset; if (si < 0 || si >= (int)Size) continue; ret[i] = element(si); } return ret; } //! \~english Writes \a v into this vector starting at \a index and ignores coordinates outside the destination range. //! \~russian Записывает \a v в этот вектор, начиная с \a index, и игнорирует координаты вне диапазона назначения. template PIMathVectorT & setSubvector(int index, const PIMathVectorT & v) { for (int i = 0; i < (int)SubSize; ++i) { int si = i + index; if (si < 0 || si >= (int)Size) continue; element(si) = v[i]; } return *this; } //! \~english Returns the cross product of \a v1 and \a v2. //! \~russian Возвращает векторное произведение \a v1 и \a v2. static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); } //! \~english Returns the scalar product of \a v1 and \a v2. //! \~russian Возвращает скалярное произведение \a v1 и \a v2. static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); } //! \~english Returns the component-wise product of \a v1 and \a v2. //! \~russian Возвращает покомпонентное произведение \a v1 и \a v2. static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); } //! \~english Returns \a v2 scaled by \a v1. //! \~russian Возвращает \a v2, масштабированный на \a v1. static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; } //! \~english Returns \a v1 scaled by \a v2. //! \~russian Возвращает \a v1, масштабированный на \a v2. static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; } //! \~english Returns the component-wise division of \a v1 by \a v2. //! \~russian Возвращает покомпонентное деление \a v1 на \a v2. static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); } //! \~english Returns \a v1 divided by scalar \a v2. //! \~russian Возвращает \a v1, поделенный на скаляр \a v2. static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; } private: Type c[Size]; }; //! \~english Multiplies a fixed-size vector by a scalar from the left. //! \~russian Умножает вектор фиксированного размера на скаляр слева. template inline PIMathVectorT operator*(const Type & x, const PIMathVectorT & v) { return v * x; } //! \~english Writes a fixed-size vector to \a PICout. //! \~russian Записывает вектор фиксированного размера в \a PICout. template inline PICout operator<<(PICout s, const PIMathVectorT & v) { s.space(); s.saveAndSetControls(0); s << "Vector{"; PIMV_FOR { s << v[i]; if (i < Size - 1) s << ", "; } s << "}"; s.restoreControls(); return s; } //! \~english Two-dimensional fixed-size vector of \c int. //! \~russian Двумерный вектор фиксированного размера из \c int. typedef PIMathVectorT<2u, int> PIMathVectorT2i; //! \~english Three-dimensional fixed-size vector of \c int. //! \~russian Трехмерный вектор фиксированного размера из \c int. typedef PIMathVectorT<3u, int> PIMathVectorT3i; //! \~english Four-dimensional fixed-size vector of \c int. //! \~russian Четырехмерный вектор фиксированного размера из \c int. typedef PIMathVectorT<4u, int> PIMathVectorT4i; //! \~english Two-dimensional fixed-size vector of \c double. //! \~russian Двумерный вектор фиксированного размера из \c double. typedef PIMathVectorT<2u, double> PIMathVectorT2d; //! \~english Three-dimensional fixed-size vector of \c double. //! \~russian Трехмерный вектор фиксированного размера из \c double. typedef PIMathVectorT<3u, double> PIMathVectorT3d; //! \~english Four-dimensional fixed-size vector of \c double. //! \~russian Четырехмерный вектор фиксированного размера из \c double. typedef PIMathVectorT<4u, double> PIMathVectorT4d; #undef PIMV_FOR #define PIMV_FOR for (uint i = 0; i < c.size(); ++i) //! \~\ingroup Math //! \~\brief //! \~english Template class for dynamic-size mathematical vector //! \~russian Шаблонный класс для математического вектора динамического размера //! \details //! \~english Provides vector operations including arithmetic, normalization, angles, cross product, and dot product for dynamic-size //! vectors //! \~russian Предоставляет операции вектора включая арифметику, нормализацию, углы, векторное произведение и скалярное произведение для //! векторов динамического размера //! \tparam Type The element type (arithmetic or complex) template class PIP_EXPORT PIMathVector { typedef PIMathVector _CVector; template friend PIBinaryStream

& operator<<(PIBinaryStream

& s, const PIMathVector & v); template friend PIBinaryStream

& operator>>(PIBinaryStream

& s, PIMathVector & v); public: //! \~english Constructs a vector of \a size elements initialized with \a new_value. //! \~russian Создает вектор из \a size элементов, инициализированных значением \a new_value. PIMathVector(const uint size = 0, const Type & new_value = Type()) { c.resize(size, new_value); } //! \~english Constructs a vector from a raw \a PIVector. //! \~russian Создает вектор из контейнера \a PIVector. PIMathVector(const PIVector & val) { c = val; } //! \~english Move-constructs a vector from a raw \a PIVector. //! \~russian Создает вектор перемещением из контейнера \a PIVector. PIMathVector(PIVector && val): c(std::move(val)) {} //! \~english Constructs a vector from an initializer list. //! \~russian Создает вектор из списка инициализации. PIMathVector(std::initializer_list init_list) { c = PIVector(init_list); } //! \~english Constructs a dynamic vector from a fixed-size one. //! \~russian Создает динамический вектор из вектора фиксированного размера. template PIMathVector(const PIMathVectorT & val) { c.resize(Size); PIMV_FOR c[i] = val[i]; } //! \~english Builds the displacement vector from point \a st to point \a fn. //! \~russian Строит вектор смещения от точки \a st к точке \a fn. static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) { assert(st.size() == fn.size()); _CVector v(st.size()); for (uint i = 0; i < v.size(); ++i) v.c[i] = fn[i] - st[i]; } //! \~english Returns a vector of \a size zeros. //! \~russian Возвращает вектор из \a size нулей. static PIMathVector zeros(const uint size) { return PIMathVector(size, Type()); } //! \~english Returns a vector of \a size ones. //! \~russian Возвращает вектор из \a size единиц. static PIMathVector ones(const uint size) { return PIMathVector(size, Type(1)); } //! \~english Returns a vector filled by the arithmetic progression [\a start, \a stop) with step \a step. //! \~russian Возвращает вектор, заполненный арифметической прогрессией [\a start, \a stop) с шагом \a step. static PIMathVector arange(const Type start, const Type stop, const Type step = Type(1)) { PIVector v; for (Type i = start; i < stop; i += step) v << i; return PIMathVector(std::move(v)); } //! \~english Returns the current vector size. //! \~russian Возвращает текущий размер вектора. uint size() const { return c.size(); } //! \~english Resizes the vector and fills new coordinates with \a new_value. //! \~russian Изменяет размер вектора и заполняет новые координаты значением \a new_value. _CVector & resize(uint size, const Type & new_value = Type()) { c.resize(size, new_value); return *this; } //! \~english Returns a resized copy of this vector. //! \~russian Возвращает копию этого вектора с другим размером. _CVector resized(uint size, const Type & new_value = Type()) { _CVector tv = _CVector(*this); tv.resize(size, new_value); return tv; } //! \~english Fills all coordinates with \a v. //! \~russian Заполняет все координаты значением \a v. _CVector & fill(const Type & v) { c.fill(v); return *this; } //! \~english Adds \a v to every coordinate. //! \~russian Прибавляет \a v к каждой координате. _CVector & move(const Type & v) { PIMV_FOR c[i] += v; return *this; } //! \~english Adds another vector component-wise. //! \~russian Прибавляет другой вектор покомпонентно. _CVector & move(const _CVector & v) { assert(c.size() == v.size()); PIMV_FOR c[i] += v[i]; return *this; } //! \~english Swaps two coordinates in place. //! \~russian Меняет местами две координаты. _CVector & swapElements(uint f, uint s) { piSwap(c[f], c[s]); return *this; } //! \~english Returns the squared Euclidean length. //! \~russian Возвращает квадрат евклидовой длины. Type lengthSqr() const { Type tv(0); PIMV_FOR tv += c[i] * c[i]; return tv; } //! \~english Returns the Euclidean length. //! \~russian Возвращает евклидову длину. Type length() const { return std::sqrt(lengthSqr()); } //! \~english Returns the Manhattan length. //! \~russian Возвращает манхэттенскую длину. Type manhattanLength() const { Type tv(0); PIMV_FOR tv += piAbs(c[i]); return tv; } //! \~english Returns the cosine of the angle to \a v. //! \~russian Возвращает косинус угла к вектору \a v. Type angleCos(const _CVector & v) const { assert(c.size() == v.size()); Type tv = v.length() * length(); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); return dot(v) / tv; } //! \~english Returns the sine of the angle to \a v. //! \~russian Возвращает синус угла к вектору \a v. Type angleSin(const _CVector & v) const { assert(c.size() == v.size()); Type tv = angleCos(v); return std::sqrt(Type(1) - tv * tv); } //! \~english Returns the angle to \a v in radians. //! \~russian Возвращает угол к вектору \a v в радианах. Type angleRad(const _CVector & v) const { return std::acos(angleCos(v)); } //! \~english Returns the angle to \a v in degrees. //! \~russian Возвращает угол к вектору \a v в градусах. Type angleDeg(const _CVector & v) const { return toDeg(angleRad(v)); } //! \~english Returns the projection of this vector onto \a v. //! \~russian Возвращает проекцию этого вектора на \a v. _CVector projection(const _CVector & v) { assert(c.size() == v.size()); Type tv = v.length(); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); return v * (dot(v) / tv); } //! \~english Normalizes this vector in place. //! \~russian Нормализует этот вектор на месте. _CVector & normalize() { Type tv = length(); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); if (tv == Type(1)) return *this; PIMV_FOR c[i] /= tv; return *this; } //! \~english Returns a normalized copy of this vector. //! \~russian Возвращает нормализованную копию этого вектора. _CVector normalized() { _CVector tv(*this); tv.normalize(); return tv; } //! \~english Returns true when all coordinates are zero. //! \~russian Возвращает true, если все координаты равны нулю. bool isNull() const { PIMV_FOR if (c[i] != Type(0)) return false; return true; } //! \~english Returns true when the vector contains allocated storage. //! \~russian Возвращает true, если у вектора есть выделенное хранилище. bool isValid() const { return !c.isEmpty(); } //! \~english Returns true when this vector is orthogonal to \a v. //! \~russian Возвращает true, если этот вектор ортогонален \a v. bool isOrtho(const _CVector & v) const { return dot(v) == Type(0); } //! \~english Returns writable access to a coordinate. //! \~russian Возвращает доступ на запись к координате. Type & operator[](uint index) { return c[index]; } //! \~english Returns read-only access to a coordinate. //! \~russian Возвращает доступ только для чтения к координате. const Type & operator[](uint index) const { return c[index]; } //! \~english Returns a coordinate by value. //! \~russian Возвращает координату по значению. Type at(uint index) const { return c[index]; } //! \~english Assigns the same value to all coordinates. //! \~russian Присваивает всем координатам одно и то же значение. _CVector & operator=(const Type & v) { PIMV_FOR c[i] = v; return *this; } //! \~english Compares two vectors component-wise. //! \~russian Сравнивает два вектора покомпонентно. bool operator==(const _CVector & v) const { return c == v.c; } //! \~english Returns true when vectors differ in at least one coordinate. //! \~russian Возвращает true, если векторы различаются хотя бы по одной координате. bool operator!=(const _CVector & v) const { return c != v.c; } //! \~english Adds \a v component-wise. //! \~russian Прибавляет \a v покомпонентно. void operator+=(const _CVector & v) { assert(c.size() == v.size()); PIMV_FOR c[i] += v[i]; } //! \~english Subtracts \a v component-wise. //! \~russian Вычитает \a v покомпонентно. void operator-=(const _CVector & v) { assert(c.size() == v.size()); PIMV_FOR c[i] -= v[i]; } //! \~english Multiplies all coordinates by \a v. //! \~russian Умножает все координаты на \a v. void operator*=(const Type & v) { PIMV_FOR c[i] *= v; } //! \~english Divides all coordinates by \a v. //! \~russian Делит все координаты на \a v. void operator/=(const Type & v) { assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); PIMV_FOR c[i] /= v; } //! \~english Returns the vector with inverted sign. //! \~russian Возвращает вектор с противоположным знаком. _CVector operator-() const { _CVector tv(c.size()); PIMV_FOR tv[i] = -c[i]; return tv; } //! \~english Returns the component-wise sum with \a v. //! \~russian Возвращает покомпонентную сумму с \a v. _CVector operator+(const _CVector & v) const { assert(c.size() == v.size()); _CVector tv(*this); PIMV_FOR tv[i] += v[i]; return tv; } //! \~english Returns the component-wise difference with \a v. //! \~russian Возвращает покомпонентную разность с \a v. _CVector operator-(const _CVector & v) const { assert(c.size() == v.size()); _CVector tv(*this); PIMV_FOR tv[i] -= v[i]; return tv; } //! \~english Returns a copy scaled by \a v. //! \~russian Возвращает копию, масштабированную на \a v. _CVector operator*(const Type & v) const { _CVector tv(*this); PIMV_FOR tv[i] *= v; return tv; } //! \~english Returns a copy divided by \a v. //! \~russian Возвращает копию, поделенную на \a v. _CVector operator/(const Type & v) const { assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); _CVector tv(*this); PIMV_FOR tv[i] /= v; return tv; } //! \~english Returns the 3D cross product with \a v. //! \~russian Возвращает 3D-векторное произведение с \a v. _CVector cross(const _CVector & v) const { assert(c.size() == 3); assert(v.size() == 3); _CVector tv(3); tv[0] = c[1] * v[2] - v[1] * c[2]; tv[1] = c[2] * v[0] - v[2] * c[0]; tv[2] = c[0] * v[1] - v[0] * c[1]; return tv; } //! \~english Returns the scalar product with \a v. //! \~russian Возвращает скалярное произведение с \a v. Type dot(const _CVector & v) const { assert(c.size() == v.size()); Type tv(0); PIMV_FOR tv += c[i] * v[i]; return tv; } //! \~english Returns the component-wise product with \a v. //! \~russian Возвращает покомпонентное произведение с \a v. _CVector mul(const _CVector & v) const { assert(c.size() == v.size()); _CVector tv(*this); PIMV_FOR tv[i] *= v[i]; return tv; } //! \~english Returns a copy scaled by \a v. //! \~russian Возвращает копию, масштабированную на \a v. _CVector mul(const Type & v) const { return (*this) * v; } //! \~english Returns the component-wise division by \a v. //! \~russian Возвращает покомпонентное деление на \a v. _CVector div(const _CVector & v) const { assert(c.size() == v.size()); _CVector tv(*this); PIMV_FOR { assert(std::abs(v[i]) > PIMATHVECTOR_ZERO_CMP); tv[i] /= v[i]; } return tv; } //! \~english Returns a copy divided by \a v. //! \~russian Возвращает копию, поделенную на \a v. _CVector div(const Type & v) const { return (*this) / v; } //! \~english Returns the distance from this 2D point to the line through \a lp0 and \a lp1. //! \~russian Возвращает расстояние от этой 2D-точки до прямой через \a lp0 и \a lp1. Type distToLine(const _CVector & lp0, const _CVector & lp1) { assert(c.size() == lp0.size()); assert(c.size() == lp1.size()); _CVector a = _CVector::fromTwoPoints(lp0, lp1); Type tv = a.length(); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); _CVector b = _CVector::fromTwoPoints(lp0, *this); return piAbs(a[0] * b[1] - a[1] * b[0]) / tv; } //! \~english Returns the underlying \a PIVector copy. //! \~russian Возвращает копию базового контейнера \a PIVector. PIVector toVector() const { return c; } //! \~english Applies \a f to every coordinate without modifying the vector. //! \~russian Применяет \a f к каждой координате без изменения вектора. void forEach(std::function f) const { c.forEach(std::move(f)); } //! \~english Applies \a f to every coordinate and returns this vector. //! \~russian Применяет \a f к каждой координате и возвращает этот вектор. _CVector & forEach(std::function f) { c.forEach(std::move(f)); return *this; } //! \~english Returns a writable pointer to contiguous vector data. //! \~russian Возвращает указатель на непрерывные данные вектора для записи. inline Type * data() { return c.data(); } //! \~english Returns a read-only pointer to contiguous vector data. //! \~russian Возвращает указатель на непрерывные данные вектора только для чтения. inline const Type * data() const { return c.data(); } //! \~english Returns the cross product of \a v1 and \a v2. //! \~russian Возвращает векторное произведение \a v1 и \a v2. static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); } //! \~english Returns the scalar product of \a v1 and \a v2. //! \~russian Возвращает скалярное произведение \a v1 и \a v2. static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); } //! \~english Returns the component-wise product of \a v1 and \a v2. //! \~russian Возвращает покомпонентное произведение \a v1 и \a v2. static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); } //! \~english Returns \a v2 scaled by \a v1. //! \~russian Возвращает \a v2, масштабированный на \a v1. static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; } //! \~english Returns \a v1 scaled by \a v2. //! \~russian Возвращает \a v1, масштабированный на \a v2. static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; } //! \~english Returns the component-wise division of \a v1 by \a v2. //! \~russian Возвращает покомпонентное деление \a v1 на \a v2. static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); } //! \~english Returns \a v1 divided by scalar \a v2. //! \~russian Возвращает \a v1, поделенный на скаляр \a v2. static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; } private: PIVector c; }; //! \~english Multiplies a dynamic vector by a scalar from the left. //! \~russian Умножает динамический вектор на скаляр слева. template inline PIMathVector operator*(const Type & x, const PIMathVector & v) { return v * x; } #undef PIMV_FOR #ifdef PIP_STD_IOSTREAM template inline std::ostream & operator<<(std::ostream & s, const PIMathVector & v) { s << "{"; for (uint i = 0; i < v.size(); ++i) { s << v[i]; if (i < v.size() - 1) s << ", "; } s << "}"; return s; } #endif //! \~english Writes a dynamic vector to \a PICout. //! \~russian Записывает динамический вектор в \a PICout. template inline PICout operator<<(PICout s, const PIMathVector & v) { s.space(); s.saveAndSetControls(0); s << "Vector{"; for (uint i = 0; i < v.size(); ++i) { s << v[i]; if (i < v.size() - 1) s << ", "; } s << "}"; s.restoreControls(); return s; } //! \~english Serializes a dynamic vector into a \a PIBinaryStream. //! \~russian Сериализует динамический вектор в \a PIBinaryStream. template inline PIBinaryStream

& operator<<(PIBinaryStream

& s, const PIMathVector & v) { s << v.c; return s; } //! \~english Deserializes a dynamic vector from a \a PIBinaryStream. //! \~russian Десериализует динамический вектор из \a PIBinaryStream. template inline PIBinaryStream

& operator>>(PIBinaryStream

& s, PIMathVector & v) { s >> v.c; return s; } //! \~english Dynamic vector of \c int. //! \~russian Динамический вектор из \c int. typedef PIMathVector PIMathVectori; //! \~english Dynamic vector of \c double. //! \~russian Динамический вектор из \c double. typedef PIMathVector PIMathVectord; #endif // PIMATHVECTOR_H