//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Габаритные объекты. Одномерный куб. \en Bounding box objects. One-dimensional box. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __MB_RECT1D_H #define __MB_RECT1D_H #include //------------------------------------------------------------------------------ /// \ru Одномерный куб. \en One-dimensional box. /** \ingroup Mathematic_Base_3D */ // --- class MATH_CLASS MbRect1D { public: double zmin; ///< \ru Начало диапазона. \en Start of range. double zmax; ///< \ru Конец диапазона. \en End of range. public: /// \ru Конструктор по умолчанию. \en Default constructor. MbRect1D ( ) : zmin( MB_MAXDOUBLE ), zmax( -MB_MAXDOUBLE ) {} /// \ru Конструктор копирования. \en Copy constructor. MbRect1D ( const MbRect1D & ); /// \ru Конструктор по заданным значениям границ. \en Constructor by given bounds. MbRect1D ( double pmin, double pmax, bool equalize = true ); /// \ru Инициализировать неустановленным. \en Initialize unspecified. void Init ( ); /// \ru Инициализировать другим кубом. \en Initialize by another box. void Init ( const MbRect1D & ); /// \ru Инициализировать заданными значениями границ. \en Initialize by given bounds. void Init ( double pmin, double pmax, bool equalize = true ); /// \ru Создать вывернутый одномерный куб. \en Create reverted one-dimensional box. void Invert (); /// \ru Сократить одномерный куб на заданный коэффициент и расширить на дельта. \en Decrease one-dimensional box by a given factor and increase by delta. void Short ( double, bool bis = true, double delta = LENGTH_EPSILON ); /// \ru Сократить одномерный куб на заданный коэффициент относительно точки и расширить на дельта. \en Decrease one-dimensional box by a given factor relative to point and increase by delta. void Short ( double, double, bool bis = true, double delta = LENGTH_EPSILON ); /// \ru Включить точку. \en Include point. void Include ( double, bool bis = true, double delta = LENGTH_EPSILON ); /// \ru Установить куб. \en Set box. void Include ( const MbRect1D & , bool bis = true, double delta = LENGTH_EPSILON ); /// \ru Включить точку. \en Include point. void IncludeEx ( double ); /// \ru Установить куб. \en Set box. void IncludeEx ( const MbRect1D & ); ///< \ru Выровнять диапазон. \en Justify range. void Equalize ( double &, double & ) const; /// \ru Выровнять диапазон (zmin, zmax). \en Justify range (zmin, zmax). void Equalize ( ); /// \ru Является ли область вывернутой. \en Check if region is reverted. bool IsEmpty ( ) const; /// \ru Является ли область вырожденной. \en Check if region is degenerate. bool IsDegenert ( ) const; /// \ru Есть ли пересечение с другим прямоугольником. \en Is there intersection with another rectangle. bool IsIntersect( const MbRect1D & ) const; /// \ru Есть ли пересечение с точкой. \en Is there intersection with point. bool IsIntersect( double ) const; /// \ru Есть ли пересечение с другим прямоугольником. \en Is there intersection with another rectangle. bool IsIntersect( double, double ) const; /// \ru Есть ли пересечение с пустым кубом. \en Is there intersection with empty box. bool IsEmptyInt ( double ) const; /// \ru Загнать одномерную точку в куб. \en Drive one-dimensional point to box. void SetInR ( double & ) const; /// \ru Загнать одномерную точку в куб. \en Drive one-dimensional point to box. void SetInRect ( double & ) const; /// \ru Загнать другую область в куб. \en Drive another region to box. void SetInRect ( MbRect1D & ) const; /// \ru Получить минимум. \en Get minimum. double GetMin () const { return zmin; } /// \ru Получить максимум. \en Get maximum. double GetMax () const { return zmax; } /// \ru Задать минимум. \en Set minimum. void SetMin( double v ) { zmin = v; } /// \ru Задать максимум. \en Set maximum. void SetMax( double v ) { zmax = v; } /// \ru Получить характерный масштаб одномерного куба. \en Get characteristic scale of one-dimensional box. double GetScale () const; /// \ru Увеличить куб. \en Increase box. void Increase ( double ); /// \ru Проверить принадлежность границе первого параметра с точностью, заданной вторым. \en Check if first parameter belongs to bound with tolerance given by second parameter. bool IsBound ( double, double ) const; /// \ru Cдвинуть куб. \en Move box. void Move ( double ); /// \ru Проверить два куба на равенство с заданной точностью. \en Check equality of two boxes with given tolerance. bool IsEqual ( const MbRect1D &, double eps ) const; /// \ru Найти габарит пересечения двух габаритов. \en Find bounding box of two bounding boxes intersection. bool Intersection( const MbRect1D &, const MbRect1D &, double eps = LENGTH_EPSILON ); /// \ru Являются ли объекты равными? \en Determine whether an object is equal? bool IsSame( const MbRect1D & other, double accuracy ) const { return ( (::fabs(zmin - other.zmin) < accuracy) && (::fabs(zmax - other.zmax) < accuracy) ); } /// \ru Проверить на равенство (точность PARAM_REGION). \en Check for equality (tolerance PARAM_REGION). bool operator ==( const MbRect1D & ) const; /// \ru Проверка на меньше (точность PARAM_REGION). \en Check for lesser (tolerance PARAM_REGION). bool operator < ( const MbRect1D & ) const; }; //------------------------------------------------------------------------------ // \ru Выровнять диапазон. \en Justify range. // --- inline void MbRect1D::Equalize( double & ozmin, double & ozmax ) const { if ( ozmin > ozmax ) { double maxvalue = ozmin; ozmin = ozmax; ozmax = maxvalue; } } //------------------------------------------------------------------------------ // \ru Выровнять диапазон. \en Justify range. // --- inline void MbRect1D::Equalize() { Equalize( zmin, zmax ); } //------------------------------------------------------------------------------ // \ru Конструктор. \en Constructor. // --- inline MbRect1D::MbRect1D( double ozmin, double ozmax, bool equalize ) : zmin( ozmin ) , zmax( ozmax ) { if ( equalize ) Equalize(); // \ru Выровнять куб. \en Justify box. } //------------------------------------------------------------------------------ // \ru Конструктор. \en Constructor. // --- inline MbRect1D::MbRect1D( const MbRect1D & other ) : zmin( other.zmin ) , zmax( other.zmax ) { } //------------------------------------------------------------------------------ // \ru Инициализировать. \en Initialize. // --- inline void MbRect1D::Init() { zmin = MB_MAXDOUBLE; zmax = -MB_MAXDOUBLE; } //------------------------------------------------------------------------------ // \ru Инициализировать. \en Initialize. // --- inline void MbRect1D::Init( double ozmin, double ozmax, bool equalize ) { zmin = ozmin; // \ru Присвоить значения. \en Assign values. zmax = ozmax; if ( equalize ) Equalize(); // \ru Выровнять куб. \en Justify box. } //------------------------------------------------------------------------------ // \ru Инициализировать. \en Initialize. // --- inline void MbRect1D::Init( const MbRect1D & other ) { zmin = other.zmin; zmax = other.zmax; } //------------------------------------------------------------------------------ // \ru Сократить одномерный куб на заданный коэфициент. \en Decrease one-dimensional box by given factor. // --- inline void MbRect1D::Short( double ks, bool bis, double d ) { double delta = bis ? d : 0; double l = ( zmax - zmin ) * 0.5; double cz = zmin + l; l *= ks; l += delta; zmin = cz - l; zmax = cz + l; } //------------------------------------------------------------------------------ // \ru Сократить одномерный куб на заданный коэффициент относительно точки. \en Decrease one-dimensional box by given factor relative to point. // --- inline void MbRect1D::Short( double ks, double cz, bool bis, double d ) { double delta = bis ? d : 0; zmax = cz > zmax ? cz + delta : ( zmax - cz ) * ks + cz + delta; zmin = cz < zmin ? cz - delta : ( zmin - cz ) * ks + cz - delta; } //------------------------------------------------------------------------------ // \ru Включить одномерную точку. \en Include one-dimensional point. // --- inline void MbRect1D::Include( double other, bool bis, double delta ) { if ( other > zmax ) zmax = bis ? other + delta : other; // \ru Расширить. \en Increase. if ( other < zmin ) zmin = bis ? other - delta : other; // \ru Расширить. \en Increase. } //------------------------------------------------------------------------------ // \ru Добавить не пустой габарит. \en Add non-empty bounding box. // --- inline void MbRect1D::Include( const MbRect1D & other, bool bis, double delta ) { if ( !other.IsEmpty() ) { Include( other.zmin, bis, delta ); Include( other.zmax, bis, delta ); } } //------------------------------------------------------------------------------- // \ru Включить точку. \en Include point. // --- inline void MbRect1D::IncludeEx( double other ) { if ( other > zmax ) zmax = other; if ( other < zmin ) zmin = other; } //------------------------------------------------------------------------------- // \ru Установить куб. \en Set box. // --- inline void MbRect1D::IncludeEx( const MbRect1D & other ) { if ( !other.IsEmpty() ) { IncludeEx( other.zmin ); IncludeEx( other.zmax ); } } //------------------------------------------------------------------------------ // \ru Является ли область пустой. \en Check if region is empty. // --- inline bool MbRect1D::IsEmpty() const { return zmin > zmax; } //------------------------------------------------------------------------------ // \ru Является ли область вырожденной. \en Check if region is degenerate. // --- inline bool MbRect1D::IsDegenert() const { return zmax - zmin < LENGTH_REGION; } //------------------------------------------------------------------------------ // \ru Включение точки в прямоугольник. \en Point inclusion in rectangle. // --- inline bool MbRect1D::IsIntersect( double other ) const { return other <= zmax && other >= zmin; } //------------------------------------------------------------------------------ // \ru Включение точки в прямоугольник. \en Point inclusion in rectangle. // --- inline bool MbRect1D::IsIntersect( double z1, double z2 ) const { Equalize( z1, z2 ); return std_max( zmin, z1 ) <= std_min( zmax, z2 ); } //------------------------------------------------------------------------------ // \ru Пересечение с другим прямоугольником. \en Check intersection with another rectangle. // --- inline bool MbRect1D::IsIntersect( const MbRect1D & other ) const { return std_max( zmin, other.zmin ) <= std_min( zmax, other.zmax ); } //------------------------------------------------------------------------------ // \ru Пересечение с пустым кубом. \en Is there intersection with empty box. // --- inline bool MbRect1D::IsEmptyInt( double other ) const { return other <= zmax || other >= zmin; } //------------------------------------------------------------------------------ // \ru Загнать одномерную точку в куб. \en Drive one-dimensional point to box. // --- inline void MbRect1D::SetInR( double & z ) const { if ( z < zmin ) z = zmin; else if ( z > zmax ) z = zmax; } //------------------------------------------------------------------------------ // \ru Загнать одномерную точку в куб. \en Drive one-dimensional point to box. // --- inline void MbRect1D::SetInRect( double & z ) const { if ( IsEmpty() ) { if( !IsEmptyInt(z) ) z = zmin; } else { SetInR( z ); } } //------------------------------------------------------------------------------ // \ru Загнать другую область в куб. \en Drive another region to box. // --- inline void MbRect1D::SetInRect( MbRect1D & other ) const { SetInRect( other.zmin ); SetInRect( other.zmax ); } //------------------------------------------------------------------------------ // \ru Создать вывернутый одномерный куб. \en Create reverted one-dimensional box. // --- inline void MbRect1D::Invert() { double oldzmax = zmax; zmax = -zmin; zmin = -oldzmax; } //------------------------------------------------------------------------------ // \ru Получить характерный масштаб одномерного куба. \en Get characteristic scale of one-dimensional box. // --- inline double MbRect1D::GetScale() const { return (zmax - zmin); } //------------------------------------------------------------------------------ // \ru Увеличить куб. \en Increase box. // --- inline void MbRect1D::Increase( double delta ) { zmax += delta; zmin -= delta; } //------------------------------------------------------------------------------ // \ru Принадлежность границе первого параметра с точность заданной вторым. \en Check if the first parameter belongs to bound with tolerance given by second parameter. // --- inline bool MbRect1D::IsBound( double z, double delta ) const { return ::fabs( z - zmin ) < delta || ::fabs( z - zmax ) < delta; } //------------------------------------------------------------------------------- // \ru Сдвиг. \en Move. // --- inline void MbRect1D::Move( double shift ) { zmin += shift; zmax += shift; } //------------------------------------------------------------------------------- // \ru Равны ли двы куба. \en Check if two boxes are equal. // --- inline bool MbRect1D::IsEqual( const MbRect1D & other, double eps ) const { return ( ::fabs(zmin - other.zmin) < eps && ::fabs(zmax - other.zmax) < eps ); } //------------------------------------------------------------------------------ // \ru Проверка на равенство. \en Check for equality. // --- inline bool MbRect1D::operator == ( const MbRect1D & other ) const { return IsEqual( other, PARAM_REGION ); } //------------------------------------------------------------------------------ // \ru Проверка на меньше. \en Check for lesser. // --- inline bool MbRect1D::operator < ( const MbRect1D & other ) const { return ( zmin < other.zmin - PARAM_REGION ) || ( ( ::fabs( zmin - other.zmin ) < PARAM_REGION ) && ( zmax < other.zmax - PARAM_REGION ) ); } //------------------------------------------------------------------------------ // \ru Габарит пересечения двух габаритов. \en Bounding box of two bounding boxes intersection. // --- inline bool MbRect1D::Intersection( const MbRect1D & r1, const MbRect1D & r2, double eps ) { bool isInt = false; if ( !r1.IsEmpty() && !r2.IsEmpty() ) { eps = ::fabs( eps ); zmin = std_max( r1.zmin, r2.zmin ); zmax = std_min( r1.zmax, r2.zmax ); if ( zmax > zmin + eps ) isInt = true; } if ( !isInt ) Init(); return isInt; } #endif // __MB_RECT1D_H