//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Двумерный вектор. \en Two-dimensional vector. \~ \details \ru Определены классы: двумерный вектор и нормализованный двумерный вектор. Также определены функции, находящие различные соотношения между двумя векторами. \en Defined classes: two-dimensional vector and normalized two-dimensional vector. Also defined functions finding various relations between two vectors. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __MB_VECTOR_H #define __MB_VECTOR_H #include #include class MATH_CLASS MbDirection; class MATH_CLASS MbCartPoint; class MATH_CLASS MbPlacement; class MATH_CLASS MbHomogeneous; class MATH_CLASS MbMatrix; class MATH_CLASS MbProperties; //------------------------------------------------------------------------------ /** \brief \ru Двумерный вектор. \en Two-dimensional vector. \~ \details \ru Двумерный вектор. Определены алгебраические и геометрические операции для вектора с числом, точкой и другим вектором. \en Two-dimensional vector. Defined algebraic and geometric operations for vector and number, point or another vector. \~ \ingroup Mathematic_Base_2D */ // --- class MATH_CLASS MbVector { public : double x; ///< \ru Первая компонента вектора. \en First component of vector. double y; ///< \ru Вторая компонента вектора. \en Second component of vector. static const MbVector zero; ///< \ru Нулевой вектор. \en Zero vector. static const MbVector xAxis; ///< \ru Вектор "X" стандартного базиса. \en "X" vector of standard basis. static const MbVector yAxis; ///< \ru Вектор "Y" стандартного базиса. \en "Y" vector of standard basis. /// \ru Конструктор по умолчанию. \en Default constructor. MbVector () : x( 0.0 ), y( 0.0 ) {} /// \ru Конструктор по координатам. \en The constructor by coordinates. MbVector ( double xx, double yy ) : x( xx ), y( yy ) {} /// \ru Конструктор копирования. \en Copy constructor. MbVector ( const MbVector & dir ) : x( dir.x ), y( dir.y ) {} /// \ru Конструктор по двум точкам. \en The constructor by two points. MbVector ( const MbCartPoint & p1, const MbCartPoint & p2 ) { Init( p1, p2 ); } /// \ru Конструктор по точке. \en Constructor by point. MbVector ( const MbCartPoint & p ); /// \ru Конструктор по углу. \en Constructor by angle. explicit MbVector ( double a ) : x( ::cos(a) ), y( ::sin(a) ) {} /// \ru Конструктор по единичному вектору направления. \en Constructor by unit vector of direction. explicit MbVector ( const MbDirection & dir ); /// \ru Инициализировать по заданным точкам. \en Initialize by given points. MbVector & Init( const MbCartPoint & p1, const MbCartPoint & p2 ); /// \ru Инициализировать по заданным координатам. \en Initialize by given coordinates. MbVector & Init( double xx, double yy ) { x = xx; y = yy; return *this; } /// \ru Инициализировать по заданному вектору. \en Initialize by given vector. template MbVector & Init( const Vector & v ) { x = v.x; y = v.y; return *this; } /// \ru Обнулить вектор. \en Set vector coordinates to zero. MbVector & SetZero() { x = y = 0.0; return *this; } /// \ru Проверить на равенство. \en Check for equality. bool operator == ( const MbVector & with ) const; /// \ru Проверить на равенство. \en Check for equality. bool Equal( const MbVector & with ) const; /// \ru Проверить на неравенство. \en Check for inequality. bool operator != ( const MbVector & with ) const; /// \ru Вычислить длину вектора. \en Calculate vector length. double Length() const; /// \ru Рассчитать квадрат длины вектора. \en Calculate vector length square double Length2() const; /// \ru Нормализовать вектор. \en Normalize a vector. bool Normalize(); /// \ru Вернуть нормализованную копию вектора. \en Return normalized copy of vector. MbVector GetNormalized() const; /// \ru Повернуть вектор на угол angle. \en Rotate vector by an angle 'angle'. MbVector & Rotate( double angle ); /// \ru Повернуть вектор на угол, заданный направлением. \en Rotate vector by an angle that defined by direction. MbVector & Rotate( const MbDirection & angle ); /// \ru Преобразовать в соответствии с матрицей matr. \en Transform according to matrix 'matr'. MbVector & Transform( const MbMatrix & matr); /// \ru Вычислить угол по нормализованному вектору. \en Calculate an angle by normalized vector. double DirectionAngle() const; /// \ru Сложить два вектора. \en Sum up two vectors. MbVector operator + ( const MbVector & ) const; /// \ru Сложить вектор и точку. \en Sum up vector and point. MbVector operator + ( const MbCartPoint & ) const; /// \ru Вычесть из вектора вектор. \en Subtract vector from vector. MbVector operator - ( const MbVector & ) const; /// \ru Вычесть из вектора точку. \en Subtract point from vector. MbVector operator - ( const MbCartPoint & ) const; /// \ru Унарный минус. \en Unary minus. MbVector operator - () const; /// \ru Умножить вектор на число. \en Multiply vector by number. MbVector operator * ( double factor ) const; /// \ru Разделить вектор на число. \en Divide vector by number. MbVector operator / ( double factor ) const; /// \ru Сложить два вектора. \en Sum up two vectors. MbVector & operator += ( const MbVector & ); /// \ru Вычесть из вектора вектор. \en Subtract vector from vector. MbVector & operator -= ( const MbVector & ); /// \ru Умножить вектор на число. \en Multiply vector by number. MbVector & operator *= ( double ); /// \ru Разделить вектор на число. \en Divide vector by number. MbVector & operator /= ( double ); /// \ru Скалярное умножение двух векторов. \en Scalar product of two vectors. double operator * ( const MbVector & ) const; /// \ru Скалярное умножение двух векторов. \en Scalar product of two vectors. double operator * ( const MbDirection & ) const; /// \ru Векторное умножение двух векторов. \en Vector product of two vectors. double operator | ( const MbVector & ) const; /// \ru Вычислить вектор как копию данного вектора, преобразованную матрицей. \en Calculate the vector as this copy transformed by the matrix. MbVector operator * ( const MbMatrix & ) const; /// \ru Делает вектор перпендикулярным самому себе, а именно задает вектор (-y, x). \en Makes a vector orthogonal to itself, namely sets the vector (-y, x). MbVector & Perpendicular(); /// \ru Выдать перпендикуляр к вектору, а именно вектор (-y, x). \en Returns a vector orthogonal to this vector, namely the vector (-y, x). MbVector operator ~ () const; /// \ru Присвоить вектору значения другого вектора. \en Assign the value of another vector to the vector. MbVector & operator = ( const MbVector & ); /// \ru Присвоить вектору значения координат точки. \en Assign point coordinate values to vector. MbVector & operator = ( const MbCartPoint & ); /// \ru Присвоить вектору значения однородных координат точки. \en Assign uniform point coordinate values to vector. MbVector & operator = ( const MbHomogeneous & ); /// \ru Присвоить вектору значения нормализованного вектора. \en Assign normalized vector values to vector. MbVector & operator = ( const MbDirection & ); /// \ru Доступ к координате по индексу. \en Access to a coordinate by an index. double & operator [] ( size_t i ) { return i ? y : x; }; /// \ru Значение координаты по индексу. \en The value of a coordinate by an index. double operator [] ( size_t i ) const { return i ? y : x; }; /// \ru Количество координат точки. \en The number of point coordinates. static size_t GetDimension() { return 2; } /// \ru Дать положение вектора относительно текущего вектора. \en Give vector location relative to current vector. int Relative( const MbVector & ) const; /// \ru Проверить на вырожденность. \en Check for degeneracy. bool IsDegenerate( double lenEps = Math::LengthEps ) const; /// \ru Проверить нормализован ли вектор. \en Check if vector is normalized. bool IsNormalized( double eps = LENGTH_EPSILON ) const; /// \ru Проверить коллинеарность по скалярному произведению. \en Check colinearity by dot product. bool RoundColinear( const MbVector & with, double eps = Math::paramNear ) const; /// \ru Проверить коллинеарность. \en Check colinearity. bool Colinear ( const MbVector & with, double eps = Math::AngleEps ) const; /// \ru Проверить ортогональность. \en Check orthogonality. bool Orthogonal ( const MbVector & with, double eps = Math::AngleEps ) const; /// \ru Проверить коллинеарность. \en Check colinearity. bool operator || ( const MbVector & with ) const { return Colinear(with); } /// \ru Сменить направление вектора на противоположное. \en Change vector direction to opposite. void Invert(); /// \ru Масштабировать компоненты вектора. \en Scale components of vector. void Scale( double sx, double sy ) { x *= sx, y *= sy; } // \ru Присвоение вектору значений \en Assign values to vector /// \ru Приравнять вектору вектор v1, умноженный на t1. \en Equate vector with vector v1 multiplied by t1. void Set( const MbVector & v1, double t1 ); /// \ru Приравнять вектору сумму векторов v1 и v2, умноженных на t1 и t2 соответственно. \en Equate vector with sum of vectors v1 and v2 multiplied with t1 and t2 correspondingly. void Set( const MbVector & v1, double t1, const MbVector & v2, double t2 ); /// \ru Приравнять вектору сумму векторов v1, v2 и v3, умноженных на t1, t2 и t3 соответственно. \en Equate vector with sum of vectors v1, v2 and v3 multiplied with t1, t2 and t3 correspondingly. void Set( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3 ); /// \ru Приравнять вектору сумму векторов v1, v2, v3 и v4, умноженных на t1, t2, t3 и t4 соответственно. \en Equate vector with sum of vectors v1, v2, v3 and v4 multiplied with t1, t2, t3 and t4 correspondingly. void Set( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3, const MbVector & v4, double t4 ); /// \ru Приравнять вектору сумму нормализованных векторов v1 и v2, умноженных на t1 и t2 соответственно. \en Equate vector with sum of normalized vectors v1 and v2 multiplied with t1 and t2 correspondingly. void Set( const MbDirection & v1, double t1, const MbDirection & v2, double t2 ); /// \ru Приравнять координаты вектора координатам суммы точек v1 и v2, умноженных на t1 и t2 соответственно. \en Equate vector coordinates with sum of points v1 and v2 multiplied with t1 and t2 correspondingly. void Set( const MbCartPoint & v1, double t1, const MbCartPoint & v2, double t2 ); /// \ru Приравнять координаты вектора координатам суммы точек v1, v2 и v3, умноженных на t1, t2 и t3 соответственно. \en Equate vector coordinates with coordinates of sum of vectors v1, v2 and v3 multiplied with t1, t2 and t3 correspondingly. void Set( const MbCartPoint & v1, double t1, const MbCartPoint & v2, double t2, const MbCartPoint & v3, double t3 ); /// \ru Приравнять координаты вектора координатам суммы точек v1, v2, v3 и v4, умноженных на t1, t2, t3 и t4 соответственно. \en Equate vector coordinates with coordinates of sum of points v1, v2, v3 and v4 multiplied with t1, t2, t3 and t4 correspondingly. void Set( const MbCartPoint & v1, double t1, const MbCartPoint & v2, double t2, const MbCartPoint & v3, double t3, const MbCartPoint & v4, double t4 ); // \ru Добавление вектору значений \en Addition values to a vector /// \ru Прибавить к вектору вектор v1, умноженный на t1. \en Add vector v1 multiplied by t1 to a vector. void Add( const MbVector & v1, double t1 ); /// \ru Прибавить к вектору сумму векторов v1 и v2, умноженных на t1 и t2 соответственно. \en Add sum of vectors v1 and v2 multiplied with t1 and t2 correspondingly to a vector. void Add( const MbVector & v1, double t1, const MbVector & v2, double t2 ); /// \ru Прибавить к вектору сумму векторов v1, v2 и v3, умноженных на t1, t2 и t3 соответственно. \en Add sum of vectors v1, v2 and v3 multiplied with t1, t2 and t3 correspondingly to a vector. void Add( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3 ); /// \ru Прибавить к вектору сумму векторов v1, v2, v3 и v4, умноженных на t1, t2, t3 и t4 соответственно. \en Add sum of vectors v1, v2, v3 and v4 multiplied with t1, t2, t3 and t4 correspondingly to a vector. void Add( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3, const MbVector & v4, double t4 ); /// \ru Прибавить к вектору сумму единичных векторов v1 и v2, умноженные на t1 и t2 соответственно. \en Add sum of unit vectors v1 and v2 multiplied with t1 and t2 correspondingly to a vector. void Add( const MbDirection & v1, double t1, const MbDirection & v2, double t2 ); /// \ru Дать максимальную по модулю компоненту вектора. \en Give the largest absolute value of a vector. double MaxFactor() const; /// \ru Выдать свойства объекта. \en Get properties of the object. void GetProperties( MbProperties &properties ); /// \ru Записать свойства объекта. \en Set properties of the object. void SetProperties( const MbProperties &properties ); /// \ru Являются ли объекты равными? \en Are the objects equal? bool IsSame( const MbVector & other, double accuracy ) const; KNOWN_OBJECTS_RW_REF_OPERATORS_EX_BASE( MbVector, MATH_FUNC_EX ) DECLARE_NEW_DELETE_CLASS( MbVector ) DECLARE_NEW_DELETE_CLASS_EX( MbVector ) }; // MbVector //------------------------------------------------------------------------------ // \ru Длина вектора. \en Vector length. // --- inline double MbVector::Length() const { return ::_hypot( x, y ); } //------------------------------------------------------------------------------ // \ru Квадрат длины вектора. \en Vector length square. // --- inline double MbVector::Length2() const { return ( x * x + y * y ); } //------------------------------------------------------------------------------ // \ru Нормализация вектора \en Normalize a vector // --- inline bool MbVector::Normalize() { double len = ::_hypot( x, y ); // C3D_ASSERT( len > LENGTH_EPSILON || len < NULL_EPSILON ); bool res = ( len >= NULL_EPSILON ); if ( res && ::fabs(len - 1.0) > NULL_EPSILON ) { double one_len = 1.0 / len; x *= one_len; y *= one_len; C3D_ASSERT( ::fabs(1.0 - ::_hypot(x, y)) < LENGTH_EPSILON ); } return res; } //------------------------------------------------------------------------------ // \ru Вернуть нормализованную копию вектора. \en Return normalized copy of vector. // --- inline MbVector MbVector::GetNormalized() const { double len = ::_hypot( x, y ); if ( len >= NULL_EPSILON && ::fabs(len - 1.0) > NULL_EPSILON ) len = 1.0 / len; MbVector res( x * len, y * len ); return res; } //------------------------------------------------------------------------------ // \ru Сложение двух векторов; результат - вектор \en Addition of two vectors; result is vector // --- inline MbVector MbVector::operator + ( const MbVector & vector ) const { return MbVector(x + vector.x, y + vector.y); } //------------------------------------------------------------------------------ // \ru Вычитание двух векторов; результат - вектор \en Subtraction of two vectors; result is vector // --- inline MbVector MbVector::operator - ( const MbVector & v1 ) const { return MbVector( x - v1.x, y - v1.y ); } //------------------------------------------------------------------------------ // \ru Унарный минус \en Unary minus // --- inline MbVector MbVector::operator - () const { return MbVector( -x, -y ); } //------------------------------------------------------------------------------ // \ru Умножение вектора на число \en Multiply vector by number // --- inline MbVector MbVector::operator * ( double factor ) const { return MbVector( x * factor, y * factor ); } //------------------------------------------------------------------------------ // \ru Умножение скаляра на вектор \en Multiply scalar by vector // --- inline MbVector operator * ( double factor, const MbVector & v ) { return v*factor; } //------------------------------------------------------------------------------ // \ru Деление вектора на число \en Division of vector by number // --- inline MbVector MbVector::operator / ( double factor ) const { if ( ::fabs(factor) > NULL_EPSILON ) return MbVector( x / factor, y / factor ); return MbVector( x, y ); } //------------------------------------------------------------------------------ // \ru Сложение двух векторов \en Addition of two vectors // --- inline MbVector & MbVector::operator += ( const MbVector & vector ) { x += vector.x; y += vector.y; return *this; } //------------------------------------------------------------------------------ // \ru Вычитание двух векторов \en Subtraction of two vectors // --- inline MbVector & MbVector::operator -= ( const MbVector & vector ) { x -= vector.x; y -= vector.y; return *this; } //------------------------------------------------------------------------------ // \ru Умножение вектора на число \en Multiplication of vector by number // --- inline MbVector & MbVector::operator *= ( double factor ) { x *= factor; y *= factor; return *this; } //------------------------------------------------------------------------------ // \ru Деление вектора на число \en Division of vector by number // --- inline MbVector & MbVector::operator /= ( double factor ) { if ( ::fabs(factor) > NULL_EPSILON ) { x /= factor; y /= factor; } return *this; } //------------------------------------------------------------------------------ // \ru Скалярное умножение двух векторов \en Scalar product of two vectors // --- inline double MbVector::operator * ( const MbVector & vector ) const { return x * vector.x + y * vector.y; } //------------------------------------------------------------------------------ // \ru Векторное умножение двух векторов \en Vector product of two vectors // --- inline double MbVector::operator | ( const MbVector & vector ) const { return x * vector.y - y * vector.x; } //------------------------------------------------------------------------------ // \ru Перпендикуляр к вектору; результат - вектор \en Perpendicular to a vector; result is vector // --- inline MbVector MbVector::operator ~ () const { return MbVector( -y, x ); } //------------------------------------------------------------------------------ // \ru Перпендикуляр к вектору; результат - вектор \en Perpendicular to a vector; result is vector // \ru Поворот влево на 90 градусов \en Rotation to the left by 90 degrees // --- inline MbVector & MbVector::Perpendicular() { double temp = x; x = - y; y = temp; return *this; } //------------------------------------------------------------------------------ // \ru Положение вектора относительно текущего вектора. \en Vector location relative to current vector. // \ru Возвращает результат : \en Returning result: // \ru +1 - слева по направлению; \en +1 - on the left by direction; // \ru 0 - вектора коллинеарны; \en 0 - vectors are collinear; // \ru -1 - справа по направлению. \en -1 - on the right by direction. // --- inline int MbVector::Relative( const MbVector & rel ) const { double l1 = Length(); double l2 = rel.Length(); if ( l1 < Math::LengthEps() || l2 < Math::LengthEps() ) return 0; double yy = (- rel.x * y + rel.y * x) / (l1*l2); return ( ::fabs(yy) < Math::LengthEps() ) ? 0 : ( yy > 0.0 ) ? + 1 : - 1; } //------------------------------------------------------------------------------ // \ru Проверка на равенство \en Check for equality // --- inline bool MbVector::operator == (const MbVector & with) const { return ( ::fabs( x - with.x ) < Math::LengthEps ) && ( ::fabs( y - with.y ) < Math::LengthEps ); } //------------------------------------------------------------------------------ // \ru Проверка на равенство \en Check for equality // --- inline bool MbVector::Equal(const MbVector & with ) const { return ( x == with.x && y == with.y ); //-V550 } //------------------------------------------------------------------------------ // \ru Проверка на неравенство \en Check for inequality // --- inline bool MbVector::operator != (const MbVector & with) const { return !(*this == with); } //------------------------------------------------------------------------------ // \ru Проверка на вырожденность \en Check for degeneracy // --- inline bool MbVector::IsDegenerate( double lenEps ) const { return ( ::fabs( x ) < lenEps ) && ( ::fabs( y ) < lenEps ); } //------------------------------------------------------------------------------ // \ru Является ли вектор нормированным \en Check if vector is normalized // --- inline bool MbVector::IsNormalized( double eps ) const { return ( ::fabs( Length() - 1.0) < eps ); } //------------------------------------------------------------------------------ // \ru Сменить направление вектора на противоположное \en Change vector direction to opposite // --- inline void MbVector::Invert() { x = -x; y = -y; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений \en Assign values to vector // --- inline void MbVector::Set( const MbVector & v1, double t1 ) { x = v1.x * t1; y = v1.y * t1; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений \en Assign values to vector // --- inline void MbVector::Set( const MbVector & v1, double t1, const MbVector & v2, double t2 ) { x = v1.x * t1 + v2.x * t2; y = v1.y * t1 + v2.y * t2; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений \en Assign values to vector // --- inline void MbVector::Set( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3 ) { x = v1.x * t1 + v2.x * t2 + v3.x * t3; y = v1.y * t1 + v2.y * t2 + v3.y * t3; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений \en Assign values to vector // --- inline void MbVector::Set( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3, const MbVector & v4, double t4 ) { x = v1.x * t1 + v2.x * t2 + v3.x * t3 + v4.x * t4; y = v1.y * t1 + v2.y * t2 + v3.y * t3 + v4.y * t4; } //------------------------------------------------------------------------------ // \ru Добавление вектору значений \en Addition values to a vector // --- inline void MbVector::Add( const MbVector & v1, double t1 ) { x += v1.x * t1; y += v1.y * t1; } //------------------------------------------------------------------------------ // \ru Добавление вектору значений \en Addition values to a vector // --- inline void MbVector::Add( const MbVector & v1, double t1, const MbVector & v2, double t2 ) { x += v1.x * t1 + v2.x * t2; y += v1.y * t1 + v2.y * t2; } //------------------------------------------------------------------------------ // \ru Добавление вектору значений \en Addition values to a vector // --- inline void MbVector::Add( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3 ) { x += v1.x * t1 + v2.x * t2 + v3.x * t3; y += v1.y * t1 + v2.y * t2 + v3.y * t3; } //------------------------------------------------------------------------------ // \ru Добавление вектору значений \en Addition values to a vector // --- inline void MbVector::Add( const MbVector & v1, double t1, const MbVector & v2, double t2, const MbVector & v3, double t3, const MbVector & v4, double t4 ) { x += v1.x * t1 + v2.x * t2 + v3.x * t3 + v4.x * t4; y += v1.y * t1 + v2.y * t2 + v3.y * t3 + v4.y * t4; } //------------------------------------------------------------------------------- // \ru Максимальная по модулю компонента вектора \en The largest absolute value of a vector // --- inline double MbVector::MaxFactor() const { return std_max( ::fabs( x ), ::fabs( y ) ); } //------------------------------------------------------------------------------ /** \brief \ru Являются ли объекты равными? \en Are the objects equal? \~ \details \ru Равными считаются объекты, данные которых равны с заданной точностью. \en The objects are equal if their data are equal with a given accuracy. \~ \param[in] other - \ru Объект для сравнения. \en The object to compare. \~ \param[in] accuracy - \ru Точность сравнения. \en The accuracy to compare. \~ \return \ru Равны ли объекты. \en Whether the objects are equal. */ inline bool MbVector::IsSame( const MbVector & other, double accuracy ) const { return ( (::fabs(x - other.x) < accuracy) && (::fabs(y - other.y) < accuracy) ); } //////////////////////////////////////////////////////////////////////////////// // // \ru Двумерный нормализованный вектор. \en Two-dimensional normalized vector. // //////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------ /** \brief \ru Двумерный нормализованный вектор. \en Two-dimensional normalized vector. \~ \details \ru Двумерный нормализованный вектор. Определены алгебраические и геометрические операции для нормализованного вектора с числом и другим вектором. \en Two-dimensional normalized vector. Defined algebraic and geometric operations for normalized vector and number or another vector. \~ \ingroup Mathematic_Base_2D */ // --- class MATH_CLASS MbDirection { public : double ax; ///< \ru Первая компонента вектора. \en First component of vector. double ay; ///< \ru Вторая компонента вектора. \en Second component of vector. /// \ru Конструктор по умолчанию. \en Default constructor. MbDirection () : ax( 1.0 ), ay( 0.0 ) {} /// \ru Конструктор по координатам. \en The constructor by coordinates. MbDirection ( double _ax, double _ay ) : ax( _ax ), ay( _ay ) { Normalize(); } /// \ru Конструктор по углу. \en Constructor by angle. explicit MbDirection ( double a ) : ax( ::cos(a) ), ay( ::sin(a) ) {} /// \ru Конструктор копирования. \en Copy constructor. MbDirection ( const MbDirection & dir ) : ax( dir.ax ), ay( dir.ay ) {} /// \ru Конструктор по двум точкам. \en Constructor by two points. MbDirection ( const MbCartPoint & p1, const MbCartPoint & p2 ) { Calculate( p1, p2 ); } /// \ru Повернуть нормализованный вектор на угол angle. \en Rotate normalized vector by an angle 'angle'. void Rotate( double angle ); /// \ru Повернуть вектор на угол, заданный направлением. \en Rotate vector by an angle that defined by direction. void Rotate( const MbDirection & ); /// \ru Преобразовать в соответствии с матрицей matr. \en Transform according to matrix 'matr'. void Transform( const MbMatrix & ); /// \ru Вычислить угол по нормализованному вектору. \en Calculate an angle by normalized vector. double DirectionAngle() const; /// \ru Вычислить направление по 2 точкам. \en Calculate direction by two points. void Calculate( const MbCartPoint & from, const MbCartPoint & to); /// \ru Нормализовать вектор. \en Normalize a vector. void Normalize(); /// \ru Унарный минус. \en Unary minus. MbDirection operator - () const; /// \ru Сложить два нормализованных вектора. \en Sum up two normalized vectors. MbDirection operator + ( const MbDirection & ) const; /// \ru Найти перпендикуляр к нормализованному вектору. \en Find perpendicular to a normalized vector. MbDirection operator ~ () const; /// \ru Найти перпендикуляр к нормализованному вектору. \en Find perpendicular to a normalized vector. void Perpendicular(); /// \ru Проверить на равенство. \en Check for equality. bool operator == ( const MbDirection & ) const; /// \ru Проверить на равенство. \en Check for equality. bool Equal( const MbDirection & ) const; /// \ru Проверить на неравенство. \en Check for inequality. bool operator != ( const MbDirection & ) const; /// \ru Проверить коллинеарность. \en Check colinearity. bool Colinear ( const MbDirection &, double eps = Math::AngleEps ) const; /// \ru Проверить ортогональность. \en Check orthogonality. bool Orthogonal( const MbDirection &, double eps = Math::AngleEps ) const; /// \ru Проверить коллинеарность. \en Check colinearity. bool Colinear ( const MbVector & with, double eps = Math::AngleEps ) const; /// \ru Проверить ортогональность. \en Check orthogonality. bool Orthogonal( const MbVector & with, double eps = Math::AngleEps ) const; /// \ru Сменить направление вектора на противоположное. \en Change vector direction to opposite. void Invert(); /// \ru Присвоить значение вектору по заданному углу. \en Assign value to vector by given angle. void operator = ( double angle ) { Set( angle ); } /// \ru Присвоить значение вектору по заданному вектору. \en Assign value to vector by given vector. void operator = ( const MbVector & ); /// \ru Присвоить значение вектору по заданной точке. \en Assign value to vector by given point. void operator = ( const MbCartPoint & ); /// \ru Умножить вектор на число. \en Multiply vector by number. MbVector operator * ( double ) const; /// \ru Сложить два вектора. \en Sum up two vectors. void operator += ( const MbDirection & ); /// \ru Найти разность векторов. \en Find the difference of vectors. void operator -= ( const MbDirection & ); // void operator *= ( double ); /// \ru Скалярное умножение двух векторов. \en Scalar product of two vectors. double operator * ( const MbDirection & ) const; /// \ru Векторное умножение двух векторов. \en Vector product of two vectors. double operator | ( const MbDirection & ) const; /// \ru Инициализировать по координатам. \en Initialize by coordinates. void Init( double xx, double yy ) { ax = xx; ay = yy; Normalize(); } /// \ru Инициализировать по координатам другого вектора. \en Initialize by coordinates of a vector. void Init( const MbDirection & dir ) { ax = dir.ax; ay = dir.ay; } /// \ru Инициализировать по заданному углу. \en Initialize by given angle. void Set( double angle ) { ax = ::cos( angle ); ay = ::sin( angle ); } /// \ru Найти положение вектора относительно текущего вектора. \en Find vector location relative to current vector. int Relative( const MbDirection & ) const; /// \ru Проверить на вырожденность. \en Check for degeneracy. bool IsDegenerate( double lenEps = Math::LengthEps ) const; /// \ru Выдать свойства объекта. \en Get properties of the object. void GetProperties( MbProperties &properties ); /// \ru Записать свойства объекта. \en Set properties of the object. void SetProperties( const MbProperties &properties ); /// \ru Являются ли объекты равными? \en Are the objects equal? bool IsSame( const MbDirection & other, double accuracy ) const; KNOWN_OBJECTS_RW_REF_OPERATORS_EX_BASE( MbDirection, MATH_FUNC_EX ) DECLARE_NEW_DELETE_CLASS( MbDirection ) DECLARE_NEW_DELETE_CLASS_EX( MbDirection ) }; // MbDirection /** \} */ //------------------------------------------------------------------------------ // \ru Нормализация вектора \en Normalize a vector // --- inline void MbDirection::Normalize() { double len = ::_hypot( ax, ay ); if ( len >= NULL_EPSILON ) { double k = 1.0 / len; ax *= k; ay *= k; } } //------------------------------------------------------------------------------ // \ru Конструктор по нормализованному вектору \en Constructor by a normalized vector // --- inline MbVector::MbVector( const MbDirection & dir ) { x = dir.ax; y = dir.ay; } //------------------------------------------------------------------------------ // \ru Присвоить вектору значения другого вектора. \en Assign the value of another vector to the vector. // --- inline MbVector & MbVector::operator = ( const MbVector & v ) { x = v.x; y = v.y; return *this; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений нормализованного вектора \en Assign normalized vector values to vector // --- inline MbVector & MbVector::operator = ( const MbDirection & dir ) { x = dir.ax; y = dir.ay; return *this; } //------------------------------------------------------------------------------ // \ru Скалярное умножение двух векторов \en Scalar product of two vectors // --- inline double MbVector::operator * ( const MbDirection & vector ) const { return x * vector.ax + y * vector.ay; } //------------------------------------------------------------------------------ // \ru Присвоение вектору значений \en Assign values to vector // --- inline void MbVector::Set( const MbDirection & v1, double t1, const MbDirection & v2, double t2 ) { x = v1.ax * t1 + v2.ax * t2; y = v1.ay * t1 + v2.ay * t2; } //------------------------------------------------------------------------------ // \ru Добавление вектору значений \en Addition values to a vector // --- inline void MbVector::Add( const MbDirection & v1, double t1, const MbDirection & v2, double t2 ) { x += v1.ax * t1 + v2.ax * t2; y += v1.ay * t1 + v2.ay * t2; } //------------------------------------------------------------------------------ // \ru Присвоение вектора \en Assignment of vector // --- inline void MbDirection::operator = ( const MbVector & vect ) { double d = vect.Length(); if ( d >= NULL_EPSILON ) { ax = vect.x / d; ay = vect.y / d; } else { ax = ay = 0.0; } } //------------------------------------------------------------------------------ // \ru Унарный минус \en Unary minus // --- inline MbDirection MbDirection::operator - () const { return MbDirection( - ax, - ay ); } //------------------------------------------------------------------------------ // \ru Сложение двух нормализованных векторов \en Addition of two normalized vectors // \ru Результат - нормализованный вектор \en Result is normalized vector // --- inline MbDirection MbDirection::operator + ( const MbDirection & dir ) const { double xx = ax + dir.ax; double yy = ay + dir.ay; double d = ::_hypot( xx, yy ); if ( d <= NULL_EPSILON ) return MbDirection( ax, ay ); double k = 1.0 / d; return MbDirection( xx*k, yy*k ); } //------------------------------------------------------------------------------ // \ru Перпендикуляр к нормализованному вектору \en Perpendicular to a normalized vector // --- inline MbDirection MbDirection::operator ~ () const { return MbDirection( - ay, ax ); } //------------------------------------------------------------------------------ // \ru Перпендикуляр к нормализованному вектору \en Perpendicular to a normalized vector // --- inline void MbDirection::Perpendicular() { double temp = ax; ax = - ay; ay = temp; } //------------------------------------------------------------------------------ // \ru Умножение вектора на число \en Multiplication of vector by number // --- inline MbVector MbDirection::operator * ( double factor ) const { return MbVector( ax * factor, ay * factor ); } //------------------------------------------------------------------------------ // \ru Сложение двух векторов \en Addition of two vectors // --- inline void MbDirection::operator += ( const MbDirection & dir ) { double xx = ax + dir.ax; double yy = ay + dir.ay; double d = ::_hypot( xx, yy ); if ( d > NULL_EPSILON ) { ax = xx / d; ay = yy / d; } } //------------------------------------------------------------------------------ // \ru Вычитание двух векторов \en Subtraction of two vectors // --- inline void MbDirection::operator -= ( const MbDirection & dir ) { double xx = ax - dir.ax; double yy = ay - dir.ay; double d = ::_hypot( xx, yy ); if ( d > NULL_EPSILON ) { ax = xx/d; ay = yy/d; } } //------------------------------------------------------------------------------ // \ru Оператор \en Operator // --- //inline void MbDirection::operator *= ( double factor ) //{ // ax *= factor; // ay *= factor; //} //------------------------------------------------------------------------------ // \ru Скалярное умножение двух векторов \en Scalar product of two vectors // --- inline double MbDirection::operator * ( const MbDirection & dir2 ) const { return ax * dir2.ax + ay * dir2.ay; } //------------------------------------------------------------------------------ // \ru Векторное умножение двух векторов \en Vector product of two vectors // --- inline double MbDirection::operator | ( const MbDirection & dir2 ) const { return ax * dir2.ay - ay * dir2.ax; } //------------------------------------------------------------------------------ // \ru Проверка на равенство \en Check for equality // --- inline bool MbDirection::operator == ( const MbDirection & with) const { return ( ::fabs( ax - with.ax ) < Math::LengthEps ) && ( ::fabs( ay - with.ay ) < Math::LengthEps ); } //------------------------------------------------------------------------------ // \ru Проверка на равенство \en Check for equality // --- inline bool MbDirection::Equal( const MbDirection & with ) const { return ( ax == with.ax && ay == with.ay ); //-V550 } //------------------------------------------------------------------------------ // \ru Проверка на неравенство \en Check for inequality // --- inline bool MbDirection::operator != ( const MbDirection & with) const { return !(*this == with); } //------------------------------------------------------------------------------ // \ru Проверка коллинеарности \en Check for colinearity // --- inline bool MbDirection::Colinear( const MbDirection & with, double eps ) const { return (::fabs( ax * with.ay - ay * with.ax ) < eps); } //------------------------------------------------------------------------------ // \ru Проверка ортогональности \en Check for orthogonality // --- inline bool MbDirection::Orthogonal( const MbDirection & with, double eps ) const { return (::fabs(*this * with) <= eps); } //------------------------------------------------------------------------------ // \ru Проверка коллинеарности \en Check for colinearity // --- inline bool MbDirection::Colinear( const MbVector & with, double eps ) const { MbVector vect( *this ); return vect.Colinear( with, eps ); } //------------------------------------------------------------------------------ // \ru Проверка ортогональности \en Check for orthogonality // --- inline bool MbDirection::Orthogonal( const MbVector & with, double eps ) const { MbVector vect( *this ); return vect.Orthogonal( with, eps ); } //------------------------------------------------------------------------------ // \ru Проверка на вырожденность \en Check for degeneracy // --- inline bool MbDirection::IsDegenerate( double lenEps ) const { return ( ::fabs( ax ) < lenEps ) && ( ::fabs( ay ) < lenEps ); } //------------------------------------------------------------------------------ // \ru Сменить направление вектора на противоположное \en Change vector direction to opposite // --- inline void MbDirection::Invert() { ax = -ax; ay = -ay; } //------------------------------------------------------------------------------ // \ru Положение вектора относительно текущего вектора \en Vector location relative to current vector // \ru Возвращает результат : \en Returning result: // \ru +1 - слева по направлению; \en +1 - on the left by direction; // \ru 0 - вектора коллинеарны; \en 0 - vectors are collinear; // \ru -1 - справа по направлению. \en -1 - on the right by direction. // --- inline int MbDirection::Relative( const MbDirection & rel ) const { double y = - rel.ax * ay + rel.ay * ax; return ( ::fabs( y ) < Math::LengthEps() ) ? 0 : ( y > 0 ) ? + 1 : - 1; } //------------------------------------------------------------------------------ /** \brief \ru Являются ли объекты равными? \en Are the objects equal? \~ \details \ru Равными считаются объекты, данные которых равны с заданной точностью. \en The objects are equal if their data are equal with a given accuracy. \~ \param[in] other - \ru Объект для сравнения. \en The object to compare. \~ \param[in] accuracy - \ru Точность сравнения. \en The accuracy to compare. \~ \return \ru Равны ли объекты. \en Whether the objects are equal. */ inline bool MbDirection::IsSame( const MbDirection & other, double accuracy ) const { return ( (::fabs(ax - other.ax) < accuracy) && (::fabs(ay - other.ay) < accuracy) ); } //////////////////////////////////////////////////////////////////////////////// // // \ru Глобальные функции \en Global functions // //////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------ /** \brief \ru Вычисление минимального угла между двумя векторами \en Calculate minimal angle between two vectors \~ \details \ru Вычисление угла между двумя векторами (-пи ... пи) Возвращает результат со знаком:\n <0 находится слева от вектора v1\n >0 находится справа от вектора v2 \en Calculate angle between two vectors (-pi ... pi) Returns signed result:\n <0 to the left of vector v1\n >0 to the right of vector v2 \~ \note \ru Нормализация векторов не требуется \en Normalization of vectors is not required \~ \ingroup Mathematic_Base_2D */ inline double Angle2Vectors( const MbVector & v1, const MbVector & v2 ) { if ( v1.MaxFactor() < NULL_REGION || v2.MaxFactor() < NULL_REGION ) return 0; return ::atan2( v1|v2/*y*/, v1*v2/*x*/ ); } //------------------------------------------------------------------------------ /// \ru Вычислить "векторное" произведение двух векторов. \en Calculate "vector" product of two vectors. // --- inline double SetVecM( const MbVector & vF, const MbVector & vS ) { return (vF.x * vS.y) - (vF.y * vS.x); } namespace c3d // namespace C3D { //------------------------------------------------------------------------------ /// \ru Вектор, повернутый на pi/2 радиан против часовой стрелки. \en Vector rotated by pi/2 radians counterclockwise. //--- inline MbVector Perpendicular( MbVector vec ) { return vec.Perpendicular(); } //------------------------------------------------------------------------------ /// \ru Проверить на равенство нулю длину вектора с заданной точностью. \en Check vector length to be equaled to zero with given tolerance. // --- inline bool IsNull( const MbVector & vec, double eps ) { return ::fabs(vec.x) < eps && ::fabs(vec.y) < eps; } } // namespace C3D #endif // __MB_VECTOR_H