905577a744
- C3d aggiornamento delle librerie.
778 lines
39 KiB
C++
778 lines
39 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\file
|
|
\brief \ru Габаритный прямоугольник.
|
|
\en Bounding rectangle. \~
|
|
|
|
*/
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#ifndef __MB_RECT_H
|
|
#define __MB_RECT_H
|
|
|
|
|
|
#include <mb_cart_point.h>
|
|
#include <mb_homogeneous.h>
|
|
#include <mb_cube_tree.h>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
|
|
class MATH_CLASS MbMatrix;
|
|
class MATH_CLASS MbRect;
|
|
|
|
namespace c3d // namespace C3D
|
|
{
|
|
typedef std::pair<MbRect *, size_t> RectPtrIndex; ///< \ru Габаритный куб и индекс. \en Bounding box and index.
|
|
typedef std::pair<const MbRect *, size_t> ConstRectPtrIndex; ///< \ru Габаритный куб и индекс. \en Bounding box and index.
|
|
typedef std::vector<RectPtrIndex> RectsPtrIndices; ///< \ru Вектор габаритных кубов и индексов. \en Vector of bounding boxes and indices.
|
|
typedef std::vector<ConstRectPtrIndex> ConstRectsPtrIndices; ///< \ru Вектор габаритных кубов и индексов. \en Vector of bounding boxes and indices.
|
|
typedef std::vector<MbRect> RectsVector; ///< \ru Вектор габаритных кубов. \en Vector of bounding boxes.
|
|
typedef MbCubeTree<MbRect, MbRect, MbCartPoint> RectsTree; ///< \ru Дерево габаритных кубов. \en Tree of bounding boxes.
|
|
} // namespace C3D
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \brief \ru Возможные положения двух габаритов относительно друг друга.
|
|
\en Possible locations of two bounding boxes relative to each other. \~
|
|
\details \ru Возможные положения двух габаритов относительно друг друга.
|
|
\en Possible locations of two bounding boxes relative to each other. \~
|
|
\ingroup Mathematic_Base_2D
|
|
*/
|
|
// ---
|
|
enum TaeTwoRectPos {
|
|
rp_FirstInside, ///< \ru Первый включает в себя второй габарит. \en The first bounding box includes the second one.
|
|
rp_SecondInside, ///< \ru Второй включает в себя первый габарит. \en The second bounding box includes the first one.
|
|
rp_Intersect, ///< \ru Габариты пересекаются. \en Bounding boxes intersect.
|
|
rp_NoIntersect ///< \ru Габариты не пересекаются. \en Bounding boxes do not intersect.
|
|
};
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \brief \ru Габаритный прямоугольник.
|
|
\en Bounding rectangle. \~
|
|
\details \ru Габаритный прямоугольник в двумерном пространстве. \n
|
|
Используется для быстрого оценочного определения близости двумерных объектов.
|
|
\en Bounding box in two-dimensional space. \n
|
|
Used for fast estimation of two-dimensional objects proximity. \~
|
|
\ingroup Mathematic_Base_2D
|
|
*/
|
|
// ---
|
|
class MATH_CLASS MbRect {
|
|
public :
|
|
double left; ///< \ru Левая граница габаритного прямоугольника. \en Left bound of bounding box.
|
|
double bottom; ///< \ru Нижняя граница габаритного прямоугольника. \en Bottom bound of bounding box.
|
|
double right; ///< \ru Правая граница габаритного прямоугольника. \en Right bound of bounding box.
|
|
double top; ///< \ru Верхняя граница габаритного прямоугольника. \en Top bound of bounding box.
|
|
|
|
public:
|
|
/// \ru Конструктор пустого габарита. \en Constructor of an empty bounding box.
|
|
MbRect() { SetEmpty(); }
|
|
/// \ru Конструктор по заданным значениям границ. \en Constructor by given bounds.
|
|
MbRect( double _left, double _bottom, double _right, double _top ) : left(_left), bottom(_bottom), right(_right), top(_top) {}
|
|
/// \ru Конструктор по другому габариту. \en Constructor by another bounding box.
|
|
MbRect( const MbRect & r ) : left(r.left), bottom(r.bottom), right(r.right), top(r.top) {}
|
|
/// \ru Конструктор по двум диагональным точкам. \en The constructor by two diagonal points.
|
|
MbRect( const MbCartPoint & p1, const MbCartPoint & p2 ) {
|
|
Set(p1.x, p1.y, p2.x, p2.y);
|
|
Normalize();
|
|
}
|
|
/// \ru Конструктор по габариту с последующей трансформацией по матрице. \en Constructor by bounding box with subsequent transformation by the matrix.
|
|
MbRect( const MbRect & r, const MbMatrix & m ) : left(r.left), bottom(r.bottom), right(r.right), top(r.top) {
|
|
Transform( m );
|
|
}
|
|
#ifdef __DEBUG_MEMORY_ALLOCATE_FREE_
|
|
~MbRect(); ///< \ru Деструктор. \en Destructor.
|
|
#endif
|
|
|
|
/// \ru Установить заданные значения границ. \en Set given values of bounds.
|
|
void Set( double _left, double _bottom, double _right, double _top );
|
|
/// \ru Установить заданные значения границ. \en Set given values of bounds.
|
|
void Set( const MbRect & r );
|
|
/// \ru Установить заданные значения границ. \en Set given values of bounds.
|
|
void Set( const MbCartPoint & p1, const MbCartPoint & p2 );
|
|
/// \ru Установить значения границ как окрестность точки. \en Set values of bounds as point neighborhood.
|
|
void Set( const MbCartPoint & p, double eps );
|
|
/// \ru Установить значения границ как окрестность точки. \en Set values of bounds as point neighborhood.
|
|
void Set( const MbCartPoint & p, double dx, double dy );
|
|
/// \ru Установить нулевым. \en Set to zero.
|
|
void SetNull();
|
|
/// \ru Установить пустым ("вывернутым"). \en Set empty ("everted").
|
|
void SetEmpty();
|
|
/// \ru Проверить на пустоту. \en Check for emptiness.
|
|
bool IsEmpty() const;
|
|
/// \ru Проверить габарит на вырожденность по оси X. \en Check bounding box for degeneracy by X-axis.
|
|
bool IsDegenerateX() const;
|
|
/// \ru Проверить габарит на вырожденность по оси Y. \en Check bounding box for degeneracy by Y-axis.
|
|
bool IsDegenerateY() const;
|
|
/// \ru Проверить габариты на равенство. \en Check bounding boxes for equality.
|
|
bool IsSame( const MbRect &, double eps ) const;
|
|
/// \ru Проверить габариты на равенство. \en Check bounding boxes for equality.
|
|
bool IsSame( const MbRect &, double xeps, double yeps ) const;
|
|
|
|
/// \ru Проверить габариты на равенство. \en Check bounding boxes for equality.
|
|
bool operator == ( const MbRect & other ) const;
|
|
/// \ru Проверить габариты на неравенство. \en Check bounding boxes for inequality.
|
|
bool operator != ( const MbRect & other ) const;
|
|
/// \ru Присвоить значение другого габарита. \en Assign a value of another bounding box.
|
|
void operator = ( const MbRect & other ) { Set( other ); }
|
|
|
|
/// \ru Получить верхнюю границу. \en Get top bound.
|
|
double GetTop () const { return top; }
|
|
/// \ru Получить нижнюю границу. \en Get bottom bound.
|
|
double GetBottom() const { return bottom; }
|
|
/// \ru Получить левую границу. \en Get left bound.
|
|
double GetLeft () const { return left; }
|
|
/// \ru Получить правую границу. \en Get right bound.
|
|
double GetRight () const { return right; }
|
|
|
|
/// \ru Установить верхнюю границу. \en Set top bound.
|
|
void SetTop ( double _top ) { top = _top; }
|
|
/// \ru Установить нижнюю границу. \en Set bottom bound.
|
|
void SetBottom( double _bottom ) { bottom = _bottom; }
|
|
/// \ru Установить левую границу. \en Set left bound.
|
|
void SetLeft ( double _left ) { left = _left; }
|
|
/// \ru Установить правую границу. \en Set right bound.
|
|
void SetRight ( double _right ) { right = _right; }
|
|
|
|
/// \ru Получить минимум по X. \en Get minimum by X.
|
|
double GetXMin() const { return left; }
|
|
/// \ru Получить минимум по Y. \en Get minimum by Y.
|
|
double GetYMin() const { return bottom; }
|
|
/// \ru Получить максимум по X. \en Get maximum by X.
|
|
double GetXMax() const { return right; }
|
|
/// \ru Получить максимум по Y. \en Get maximum by Y.
|
|
double GetYMax() const { return top; }
|
|
|
|
/// \ru Получить середину по X. \en Get middle by X.
|
|
double GetXMid() const { return 0.5 * ( left + right ); }
|
|
/// \ru Получить середину по Y. \en Get middle by Y.
|
|
double GetYMid() const { return 0.5 * ( bottom + top ); }
|
|
|
|
/// \ru Установить минимум по X. \en Set minimum by X.
|
|
void SetXMin( double s ) { left = s; }
|
|
/// \ru Установить максимум по X. \en Set maximum by X.
|
|
void SetYMin( double s ) { bottom = s; }
|
|
/// \ru Установить минимум по Y. \en Set minimum by Y.
|
|
void SetXMax( double s ) { right = s; }
|
|
///< \ru Установить максимум по Y. \en Set maximum by Y.
|
|
void SetYMax( double s ) { top = s; }
|
|
|
|
/// \ru Найти ширину габарита. \en Find width of bounding box.
|
|
double Width() const { return right - left; }
|
|
/// \ru Найти высоту габарита. \en Find height of bounding box.
|
|
double Height() const { return top - bottom; }
|
|
/// \ru Дать длину по X. \en Get length by X.
|
|
double GetLengthX() const { return right - left; } //-V524
|
|
/// \ru Дать длину по Y. \en Get length by Y.
|
|
double GetLengthY() const { return top - bottom; } //-V524
|
|
/// \ru Дать половину периметра. \en Get half of perimeter.
|
|
double GetLength( double eps ) const;
|
|
/// \ru Дать площадь. \en Get area.
|
|
double GetSquare( double eps ) const;
|
|
/// \ru Дать длину диагонали. \en Get the diagonal length.
|
|
double GetDiagonal() const { return ::_hypot( left - right, top - bottom ); }
|
|
|
|
/// \ru Вычислить габарит пересечения двух габаритов. \en Calculate bounding box of two bounding boxes intersection.
|
|
bool Intersection( const MbRect & rect1, const MbRect & rect2, double eps = Math::LengthEps );
|
|
/// \ru Вычислить суммарный габарит двух габаритов. \en Calculate bounding box enclosing two bounding boxes.
|
|
bool Union ( const MbRect & rect1, const MbRect & rect2 );
|
|
|
|
/// \ru Проверить принадлежность габариту заданной точки. \en Check if the bounding box contains the given point.
|
|
bool Contains( const MbCartPoint & p, double eps = Math::LengthEps ) const;
|
|
/// \ru Проверить принадлежность габариту заданной точки. \en Check if the bounding box contains the given point.
|
|
bool Contains( double x, double y, double eps = Math::LengthEps ) const;
|
|
/// \ru Проверить принадлежность габариту заданной точки. \en Check if the bounding box contains the given point.
|
|
bool Contains( const MbCartPoint & p, double xeps, double yeps ) const;
|
|
/// \ru Проверить принадлежность габариту заданной точки. \en Check if the bounding box contains the given point.
|
|
bool Contains( double x, double y, double xeps, double yeps ) const;
|
|
/// \ru Проверить принадлежность габариту заданной координаты по X. \en Check if the bounding box contains the given X coordinate.
|
|
bool ContainsX( double x, double eps = Math::LengthEps ) const ;
|
|
/// \ru Проверить принадлежность габариту заданной координаты по Y. \en Check if the bounding box contains the given Y coordinate.
|
|
bool ContainsY( double y, double eps = Math::LengthEps ) const ;
|
|
/// \ru Вычислить коды расположения точки относительно прямоугольника. \en Calculate the codes of a point location relative to the rectangle.
|
|
void OutCodes( const MbCartPoint & p, unsigned int & outcodes, double eps = METRIC_PRECISION ) const;
|
|
|
|
/** \brief \ru Вычислить расстояние до ближайшей границы габаритного прямоугольника.
|
|
\en Calculate the distance to the nearest boundary of the bounding box. \~
|
|
\details \ru Найденное расстояние до ближайшей границы имеет отрицательное значение, если точка находится внутри, и положительное - если снаружи.
|
|
\en The calculated distance is negative if the point is inside, and is positive if it is outside. \~
|
|
\param[in] point - \ru Исследуемая точка.
|
|
\en The investigated point. \~
|
|
\return \ru Возвращает расстояние до границы.
|
|
\en Returns the distance to the boundary. \~
|
|
*/
|
|
double DistanceToPoint( const MbCartPoint & point ) const;
|
|
/// \ru Вычислить расстояние до точки. \en Calculate the distance to a point.
|
|
double DistanceToPoint( const MbCartPoint & to,
|
|
unsigned int & outcodes ) const;
|
|
|
|
/** \brief \ru Вычислить расстояние до куба.
|
|
\en Calculate the distance to the cube. \~
|
|
\details \ru Возвращается ноль, если кубы пересекаются или один содержится в другом.
|
|
\en It returns zero if the cubes intersect or one is contained in the other. \~
|
|
\param[in] cube - \ru Другой куб.
|
|
\en Other cube. \~
|
|
\param[in] eps - \ru Метрическая точность.
|
|
\en A metric tolerance. \~
|
|
\return \ru Возвращает расстояние до границы.
|
|
\en Returns the distance to the boundary. \~
|
|
*/
|
|
double DistanceToCube( const MbRect & cube, double eps = Math::metricRegion ) const;
|
|
|
|
/// \ru Вычислить минимальное и максимальное расстояния до точки. \en Calculate minimal and maximal distances to a point.
|
|
void CalcDistances( const MbCartPoint & to,
|
|
double & dmin, double & dmax,
|
|
unsigned int & outcodes ) const;
|
|
// \ru Пересекается ли габарит с другим габаритом. \en Whether the bounding box intersects with another bounding box.
|
|
/// \ru Проверить, пересекается ли габарит с другим габаритом с признаком пересечения. \en Whether the bounding box intersects with another bounding box with intersection attribute.
|
|
bool Intersect( const MbRect &, TaeTwoRectPos & ) const;
|
|
/// \ru Проверить пересекается ли габарит с другим габаритом. \en Whether the bounding box intersects with another bounding box.
|
|
bool Intersect( const MbRect & other, double eps = Math::LengthEps ) const;
|
|
/// \ru Проверить пересекается ли габарит с другим габаритом. \en Whether the bounding box intersects with another bounding box.
|
|
bool Intersect( const MbRect & other, double xeps, double yeps ) const;
|
|
/// \ru Сделать другой прямоугольник из этого, сжав его. \en Create new rectangle from the current one by shrinking.
|
|
MbRect CompressedBy( double dLeft, double dBottom,
|
|
double dRight, double dTop) const ;
|
|
|
|
/// \ru Нормализовать себя. \en Normalize oneself.
|
|
MbRect & Normalize();
|
|
/// \ru Преобразовать по матрице. \en Transform by matrix.
|
|
void Transform( const MbMatrix & );
|
|
/// \ru Масштабировать. \en Scale.
|
|
void Scale( double sx, double sy );
|
|
|
|
/// \ru Включить в себя прямоугольник. \en Enclose a rectangle.
|
|
MbRect & operator |= ( const MbRect & );
|
|
/// \ru Включить в себя точку. \en Enclose a point.
|
|
MbRect & operator |= ( const MbCartPoint & );
|
|
/// \ru Включить в себя точку. \en Enclose a point.
|
|
MbRect & operator |= ( const MbHomogeneous & );
|
|
/// \ru Включить в себя массив точек. \en Enclose an array of points.
|
|
MbRect & operator |= ( const SArray<MbCartPoint> & );
|
|
/// \ru Включить в себя массив точек. \en Enclose an array of points.
|
|
MbRect & operator |= ( const SArray<MbHomogeneous> & );
|
|
|
|
/// \ru Включить в себя точку,заданную как XY. \en Enclose a point specified as XY.
|
|
void Include( double x, double y );
|
|
/// \ru Включить в себя координату X. \en Enclose an X-coordinate.
|
|
void IncludeX( double x );
|
|
/// \ru Включить в себя координату Y. \en Enclose an Y-coordinate.
|
|
void IncludeY( double y );
|
|
/// \ru Включить в себя интервал от X - dx до X + dx. \en Enclose a range from X - dx to X + dx.
|
|
void IncludeXInterval( double x, double dx );
|
|
/// \ru Включить в себя интервал от Y - dy до Y + dy. \en Enclose a range from Y - dy to Y + dy.
|
|
void IncludeYInterval( double y, double dy );
|
|
// \ru Сдвинуть прямоугольник \en Move rectangle
|
|
/// \ru Cдвинуть прямоугольник. \en Move rectangle.
|
|
void Move( const MbVector & to );
|
|
/// \ru Cдвинуть прямоугольник. \en Move rectangle.
|
|
void Move( double dx, double dy );
|
|
/// \ru Масштабировать относительно 0. \en Scale relative to 0.
|
|
void Scale( double scale );
|
|
|
|
/// \ru Расширить прямоугольник. \en Extend rectangle.
|
|
void Enlarge( double x, double y );
|
|
/// \ru Расширить прямоугольник во все стороны. \en Extend rectangle in all directions.
|
|
void Enlarge( double delta );
|
|
|
|
/// \ru Поличить охватывающий прямоугольник. \en Get the covering rectangle.
|
|
void GetOusideRect( MbRect & r ) const { r = *this; }
|
|
/// \ru Вернуть точку центра габарита. \en Get center of the bounding box.
|
|
void GetCenter( MbCartPoint & p ) const {
|
|
p.x = (left + right) * 0.5;
|
|
p.y = (top + bottom) * 0.5;
|
|
}
|
|
|
|
// \ru Вершины габаритного прямоугольника \en Vertices of bounding box
|
|
// Y
|
|
// |
|
|
// 3 - - - 2
|
|
// | |
|
|
// | |
|
|
// 0 - - - 1 - X
|
|
//
|
|
|
|
/// \ru Дать количество вершин. \en Get count of vertices.
|
|
size_t GetVerticesCount() const { return 4; } //-V112
|
|
/// \ru Выдать вершину габаритного прямоугольника по индексу от 0 до 3. \en Get vertex of bounding rectangle by index in range from 0 to 3.
|
|
void GetVertex( size_t index, MbCartPoint & p ) const;
|
|
|
|
/// \ru Получить ссылку на себя. \en Get reference to itself.
|
|
const MbRect & GetRect() const { return *this; }
|
|
|
|
/// \ru Количество координат точки. \en The number of point coordinates.
|
|
static size_t GetDimension() { return 2; }
|
|
/// \ru Доступ к координате по индексу. \en Access to a coordinate by an index.
|
|
double GetMin( size_t k ) const { return k ? bottom : left; }
|
|
/// \ru Доступ к координате по индексу. \en Access to a coordinate by an index.
|
|
double GetMax( size_t k ) const { return k ? top : right; }
|
|
/// \ru Дать длина по стороне. \en Get side length.
|
|
double GetSideLength( size_t k ) const { return k ? ::fabs( GetLengthY() ) : ::fabs( GetLengthX() ); }
|
|
|
|
/// \ru Получить ссылку на себя. \en Get reference to itself.
|
|
const MbRect & GetCube() const { return *this; }
|
|
|
|
KNOWN_OBJECTS_RW_REF_OPERATORS_EX( MbRect, MATH_FUNC_EX )
|
|
DECLARE_NEW_DELETE_CLASS( MbRect )
|
|
DECLARE_NEW_DELETE_CLASS_EX( MbRect )
|
|
}; // MbRect
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить заданные значения границ \en Set given values of bounds
|
|
// ---
|
|
inline void MbRect::Set( double _left, double _bottom, double _right, double _top )
|
|
{
|
|
left = _left;
|
|
top = _top;
|
|
right = _right;
|
|
bottom = _bottom;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить заданные значения границ \en Set given values of bounds
|
|
// ---
|
|
inline void MbRect::Set( const MbRect & r )
|
|
{
|
|
left = r.left;
|
|
top = r.top;
|
|
right = r.right;
|
|
bottom = r.bottom;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить значения границ как окрестность точки. \en Set values of bounds as point neighborhood.
|
|
// ---
|
|
inline void MbRect::Set( const MbCartPoint & p1, const MbCartPoint & p2 )
|
|
{
|
|
left = std_min( p1.x, p2.x );
|
|
right = std_max( p1.x, p2.x );
|
|
bottom = std_min( p1.y, p2.y );
|
|
top = std_max( p1.y, p2.y );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить значения границ как окрестность точки. \en Set values of bounds as point neighborhood.
|
|
// ---
|
|
inline void MbRect::Set( const MbCartPoint & p, double eps )
|
|
{
|
|
eps = ::fabs( eps );
|
|
left = p.x - eps;
|
|
right = p.x + eps;
|
|
bottom = p.y - eps;
|
|
top = p.y + eps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить значения границ как окрестность точки. \en Set values of bounds as point neighborhood.
|
|
// ---
|
|
inline void MbRect::Set( const MbCartPoint & p, double dx, double dy )
|
|
{
|
|
dx = ::fabs( dx );
|
|
dy = ::fabs( dy );
|
|
|
|
left = p.x - dx;
|
|
right = p.x + dx;
|
|
bottom = p.y - dy;
|
|
top = p.y + dy;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить нулевым \en Set to zero
|
|
// ---
|
|
inline void MbRect::SetNull() {
|
|
left = top = right = bottom = 0;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Установить пустым ("вывернутым") \en Set empty ("everted")
|
|
// ---
|
|
inline void MbRect::SetEmpty() {
|
|
Set( MB_MAXDOUBLE, MB_MAXDOUBLE, -MB_MAXDOUBLE, -MB_MAXDOUBLE );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на пустоту \en Check for emptiness
|
|
// ---
|
|
inline bool MbRect::IsEmpty() const {
|
|
return ( left > right ) || ( bottom > top );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка габарита по оси 0X \en Check bounding box by 0X-axis
|
|
// ---
|
|
inline bool MbRect::IsDegenerateX() const {
|
|
return fabs( right - left ) < Math::LengthEps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка габарита по оси 0Y \en Check bounding box by 0Y-axis
|
|
// ---
|
|
inline bool MbRect::IsDegenerateY() const {
|
|
return fabs( top - bottom ) < Math::LengthEps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка равенства с другим прямоугольником \en Check for equality with another rectangle
|
|
// ---
|
|
inline bool MbRect::IsSame( const MbRect & other, double eps ) const {
|
|
return ::fabs( other.left - left ) < eps &&
|
|
::fabs( other.right - right ) < eps &&
|
|
::fabs( other.top - top ) < eps &&
|
|
::fabs( other.bottom - bottom ) < eps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка равенства с другим прямоугольником \en Check for equality with another rectangle
|
|
// ---
|
|
inline bool MbRect::IsSame( const MbRect & other, double xeps, double yeps ) const {
|
|
return ::fabs( other.left - left ) < xeps &&
|
|
::fabs( other.right - right ) < xeps &&
|
|
::fabs( other.top - top ) < yeps &&
|
|
::fabs( other.bottom - bottom ) < yeps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка равенства с другим прямоугольником \en Check for equality with another rectangle
|
|
// ---
|
|
inline bool MbRect::operator == ( const MbRect & other ) const {
|
|
return ::fabs( other.left - left ) < Math::LengthEps &&
|
|
::fabs( other.right - right ) < Math::LengthEps &&
|
|
::fabs( other.top - top ) < Math::LengthEps &&
|
|
::fabs( other.bottom - bottom ) < Math::LengthEps;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка неравенства с другим прямоугольником \en Check for inequality with another rectangle
|
|
// ---
|
|
inline bool MbRect::operator != ( const MbRect & other ) const {
|
|
return !( other == *this );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная точка лежит внутри прямоугольника \en Check that a given point is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::Contains( const MbCartPoint & p, double eps ) const {
|
|
return ( p.x >= (left - eps) ) && ( p.x <= (right + eps) ) &&
|
|
( p.y >= (bottom - eps) ) && ( p.y <= (top + eps) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная точка лежит внутри прямоугольника \en Check that a given point is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::Contains( double x, double y, double eps ) const {
|
|
return ( x >= (left - eps) ) && ( x <= (right + eps) ) &&
|
|
( y >= (bottom - eps) ) && ( y <= (top + eps) );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная точка лежит внутри прямоугольника \en Check that a given point is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::Contains( const MbCartPoint & p, double xeps, double yeps ) const {
|
|
return ( p.x >= (left - xeps) ) && ( p.x <= (right + xeps) ) &&
|
|
( p.y >= (bottom - yeps) ) && ( p.y <= (top + yeps) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная точка лежит внутри прямоугольника \en Check that a given point is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::Contains( double x, double y, double xeps, double yeps ) const {
|
|
return ( x >= (left - xeps) ) && ( x <= (right + xeps) ) &&
|
|
( y >= (bottom - yeps) ) && ( y <= (top + yeps) );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная координата X лежит внутри прямоугольника \en Check that given X coordinate is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::ContainsX( double x, double eps ) const {
|
|
return ( x > left - eps ) && ( x < right + eps );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка на то, что заданная координата Y лежит внутри прямоугольника \en Check that given Y coordinate is inside the rectangle
|
|
// ---
|
|
inline bool MbRect::ContainsY( double y, double eps ) const {
|
|
return ( y > bottom - eps ) && ( y < top + eps );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Вычисление кодов расположения точки относительно прямоугольника \en Calculate codes of a point location relative to the rectangle
|
|
// \ru Бит 0 - точка слева от окна \en Bit 0 - point to the left of a window
|
|
// \ru Бит 1 - точка справа от окна \en Bit 1 - point to the right of a window
|
|
// \ru Бит 2 - точка ниже окна \en Bit 2 - the point is lower than a window
|
|
// \ru Бит 3 - точка выше окна \en Bit 3 - the point is higher than a window
|
|
// ---
|
|
inline void MbRect::OutCodes( const MbCartPoint & p, unsigned int & outcodes, double eps ) const {
|
|
outcodes = ( p.x < left - eps ) |
|
|
( ( ( p.x > right + eps ) << 1 ) & 0x2 ) |
|
|
( ( ( p.y < bottom - eps ) << 2 ) & 0x4 ) | //-V112
|
|
( ( ( p.y > top + eps ) << 3 ) & 0x8 );
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Расстояние до точки: если расстояние < 0, то точка лежит внутри \en Distance to a point: if distance is less than 0 then point is inside
|
|
// ---
|
|
inline double MbRect::DistanceToPoint( const MbCartPoint & pnt ) const {
|
|
double dx = std_max( left-pnt.x, pnt.x-right );
|
|
double dy = std_max( bottom-pnt.y, pnt.y-top );
|
|
return std_max(dx,dy);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Расстояние до точки \en Distance to a point
|
|
// ---
|
|
inline double MbRect::DistanceToPoint( const MbCartPoint & to,
|
|
unsigned int & outcodes ) const
|
|
{
|
|
if ( IsEmpty() ) {
|
|
outcodes = 0xFFFF;
|
|
return 1E+6;
|
|
}
|
|
|
|
OutCodes( to, outcodes ); // \ru Вычисление кодов расположения точки \en Calculate codes of a point location
|
|
|
|
double dx = std_min( fabs( to.x - left), fabs( to.x - right) );
|
|
double dy = std_min( fabs( to.y - top), fabs( to.y - bottom) );
|
|
|
|
return ( outcodes == 0x0 ) ? std_min( dx, dy ) : // \ru Точка внутри прямоугольника \en Point is inside the rectangle
|
|
( outcodes == 0x1 || outcodes == 0x2 ) ? dx : // \ru Точка по Y - внутри, по X - вне прямоугольника \en Point is inside rectangle by Y, outside by X
|
|
( outcodes == 0x4 || outcodes == 0x8 ) ? dy : // \ru Точка по X - внутри, по Y - вне прямоугольника //-V112 \en Point is inside rectangle by X, outside by Y //-V112
|
|
::_hypot( dx, dy ); // \ru Точка по X и по Y - вне прямоугольника \en Point is outside the rectangle by X and Y
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Вычисление минимального и максимального расстояний до точки \en Calculate minimal and maximal distances to point
|
|
// ---
|
|
inline void MbRect::CalcDistances( const MbCartPoint & to,
|
|
double & dmin, double & dmax,
|
|
unsigned int & outcodes ) const
|
|
{
|
|
dmin = DistanceToPoint( to, outcodes );
|
|
|
|
if ( outcodes != 0xFFFF ) { // \ru Прямоугольник не вырожден \en Rectangle is not degenerate
|
|
dmax = ::_hypot( to.x - left, to.y - bottom );
|
|
|
|
double d = ::_hypot( to.x - left, to.y - top );
|
|
if ( d > dmax ) dmax = d;
|
|
|
|
d = ::_hypot( to.x - right, to.y - bottom );
|
|
if ( d > dmax ) dmax = d;
|
|
|
|
d = ::_hypot( to.x - right, to.y - top );
|
|
if ( d > dmax ) dmax = d;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Сделать другой прям-к из этого, сжав его \en Create a new rectangle from the current one by shrinking
|
|
// ---
|
|
inline MbRect MbRect::CompressedBy( double dLeft, double dBottom, double dRight, double dTop) const
|
|
{
|
|
if ( IsEmpty() )
|
|
return MbRect();
|
|
|
|
return MbRect(left+dLeft, bottom+dBottom, right-dRight, top-dTop);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Нормализовать себя \en Normalize oneself
|
|
// ---
|
|
inline MbRect & MbRect::Normalize() {
|
|
double c = UNDEFINED_DBL;
|
|
if ( left > right ) { c = left; left = right; right = c; }
|
|
if ( top < bottom ) { c = top; top = bottom; bottom = c; }
|
|
return *this;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя точку \en Enclose a point
|
|
// ---
|
|
inline MbRect & MbRect::operator |=( const MbCartPoint & p ) {
|
|
Include( p.x, p.y );
|
|
return *this;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя точку \en Enclose a point
|
|
// ---
|
|
inline MbRect & MbRect::operator |=( const MbHomogeneous & p ) {
|
|
Include( p.x, p.y );
|
|
return *this;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя точку,заданную как XY \en Enclose a point secified as XY
|
|
// ---
|
|
inline void MbRect::Include( double x, double y ) {
|
|
left = std_min(left, x);
|
|
bottom = std_min(bottom, y);
|
|
right = std_max(right, x);
|
|
top = std_max(top, y);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя координату X \en Enclose an X-coordinate
|
|
// ---
|
|
inline void MbRect::IncludeX( double x ) {
|
|
left = std_min(left, x);
|
|
right = std_max(right, x);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя координату Y \en Enclose an Y-coordinate
|
|
// ---
|
|
inline void MbRect::IncludeY( double y ) {
|
|
bottom = std_min(bottom, y);
|
|
top = std_max(top, y);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя интервал от X - dx до X + dx \en Enclose a range from X - dx to X + dx
|
|
// ---
|
|
inline void MbRect::IncludeXInterval( double x, double dx ) {
|
|
left = std_min( left, x - dx );
|
|
right = std_max( right, x + dx );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя интервал от Y - dy до Y + dy \en Enclose a range from Y - dy to Y + dy
|
|
// ---
|
|
inline void MbRect::IncludeYInterval( double y, double dy ) {
|
|
bottom = std_min( bottom, y - dy );
|
|
top = std_max( top, y + dy );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Включить в себя прямоугольник \en Enclose a rectangle
|
|
// ---
|
|
inline MbRect& MbRect::operator |= ( const MbRect & other ) {
|
|
left = std_min(left, other.left);
|
|
bottom = std_min(bottom, other.bottom);
|
|
right = std_max(right, other.right);
|
|
top = std_max(top, other.top);
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Сдвинуть прямоугольник \en Move rectangle
|
|
// ---
|
|
inline void MbRect::Move( const MbVector & to ) {
|
|
Move( to.x, to.y );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Сдвинуть прямоугольник \en Move rectangle
|
|
// ---
|
|
inline void MbRect::Move( double dx, double dy ) {
|
|
if ( !IsEmpty() ) {
|
|
left += dx;
|
|
right += dx;
|
|
top += dy;
|
|
bottom += dy;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Промасштабировать относительно 0 \en Scale relative to 0
|
|
// ---
|
|
inline void MbRect::Scale( double scale ) {
|
|
if ( !IsEmpty() ) {
|
|
left *= scale;
|
|
right *= scale;
|
|
top *= scale;
|
|
bottom *= scale;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Расширить прямоугольник \en Extend rectangle
|
|
// ---
|
|
inline void MbRect::Enlarge( double x, double y ) {
|
|
if ( !IsEmpty() ) {
|
|
left -= x;
|
|
right += x;
|
|
bottom -= y;
|
|
top += y;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Расширить прямоугольник во все стороны \en Extend the rectangle in all directions
|
|
// \ru НЕ ПРОВЕРЯЕТСЯ вырожденность прямоугольников !!! \en Rectangles degeneracy IS NOT CHECKED !!!
|
|
// ---
|
|
inline void MbRect::Enlarge( double delta ) {
|
|
left -= delta;
|
|
right += delta;
|
|
bottom -= delta;
|
|
top += delta;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка, пересекается ли прям-к с другим прям-ком \en Check if rectangle intersect another rectangle
|
|
// \ru НЕ ПРОВЕРЯЕТСЯ вырожденность прямоугольников !!! \en Rectangles degeneracy IS NOT CHECKED !!!
|
|
// ---
|
|
inline bool MbRect::Intersect( const MbRect & other, double eps ) const {
|
|
return std_max( left, other.left ) < std_min( right, other.right ) + eps &&
|
|
std_max( bottom, other.bottom ) < std_min( top, other.top ) + eps;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Проверка, пересекается ли прям-к с другим прям-ком \en Check if the rectangle intersect another rectangle
|
|
// \ru НЕ ПРОВЕРЯЕТСЯ вырожденность прямоугольников !!! \en Rectangles degeneracy IS NOT CHECKED !!!
|
|
// ---
|
|
inline bool MbRect::Intersect( const MbRect & other, double xeps, double yeps ) const {
|
|
return std_max( left, other.left ) < std_min( right, other.right ) + xeps &&
|
|
std_max( bottom, other.bottom ) < std_min( top, other.top ) + yeps;
|
|
}
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|