Files
SaraP 86f4bb48be Extern :
- C3d aggiornamento delle librerie ( 117960).
2023-10-12 08:53:50 +02:00

1111 lines
50 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/**
\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 <io_base.h>
#include <mb_enum.h>
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 <class Vector>
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