//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Габаритный куб геометрического объекта. \en The bounding box (cube) of a geometric object. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __MB_CUBE_H #define __MB_CUBE_H #include #include #include #include #include #include constexpr size_t CUBE_CONTROL_POINTS_COUNT = 26; ///< \ru Количество характерных точек куба. \en The number of control points of thebounding box. constexpr size_t CUBE_VERTEX_COUNT = 8; ///< \ru Количество вершин куба. \en The number of the bounding box vertices. constexpr size_t CUBE_EDGES_COUNT = 12; ///< \ru Количество рёбер куба. \en The number of the bounding box edges. constexpr size_t CUBE_FACES_COUNT = 6; ///< \ru Количество граней куба. \en The number of the bounding box faces. class MATH_CLASS MbRect; class MATH_CLASS MbRect1D; class MATH_CLASS MbCube; class MATH_CLASS MbPlacement3D; class MATH_CLASS MbCurve3D; class MATH_CLASS MbSurface; namespace c3d // namespace C3D { typedef std::pair CubeIndex; ///< \ru Габаритный куб и индекс. \en Bounding box and index. typedef std::pair IndexCube; ///< \ru Индекс и габаритный куб. \en Index and bounding box. typedef std::pair CubePtrIndex; ///< \ru Габаритный куб и индекс. \en Bounding box and index. typedef std::pair IndexCubePtr; ///< \ru Индекс и габаритный куб. \en Index and bounding box. typedef std::pair ConstCubePtrIndex; ///< \ru Габаритный куб и индекс. \en Bounding box and index. typedef std::pair IndexConstCubePtr; ///< \ru Индекс и габаритный куб. \en Index and bounding box. typedef std::vector CubesPtrIndices; ///< \ru Вектор габаритных кубов и индексов. \en Vector of bounding boxes and indices. typedef std::vector ConstCubesPtrIndices; ///< \ru Вектор габаритных кубов и индексов. \en Vector of bounding boxes and indices. typedef std::vector CubesVector; ///< \ru Вектор габаритных кубов. \en Vector of bounding boxes. typedef std::vector IndexCubeVector; ///< \ru Вектор индексов и габаритных кубов. \en Vector of indices and bounding boxes. typedef std::vector CubeIndexVector; ///< \ru Вектор индексов и габаритных кубов. \en Vector of indices and bounding boxes. typedef MbCubeTree CubesTree; ///< \ru Дерево габаритных кубов. \en Tree of bounding boxes. } // namespace C3D //------------------------------------------------------------------------------ /** \brief \ru Габаритный параллелепипед. \en The bounding box. \~ \details \ru Габаритный параллелепипед - это область 3D-пространства, ограниченная прямым параллелепипедом, грани которого параллельным плоскостям системы координат.\n Используется для быстрой оценки близости или непересечения трёхмерных объектов, содержащихся в параллелепипеде. Габаритный параллелепипед описывается парой точек, расположенных на главной диагонали куба. \en The bounding box is a domain (block) of 3D-space bounded by parallelepiped with edges parallel to the axes of coordinate system.\n It is used for quick estimation of the proximity or non-intersection of three-dimensional objects, which are contained in the "box". Faces of "box" are parallel to planes of coordinate system. The bounding box is described by a pair of points which are located on the main diagonal of a box. \~ \ingroup Mathematic_Base_3D */ // --- class MATH_CLASS MbCube { public : MbCartPoint3D pmin; ///< \ru Точка диагонали параллелепипеда с минимальными координатами. \en A point of a box diagonal with minimal coordinates. MbCartPoint3D pmax; ///< \ru Точка диагонали параллелепипеда с максимальными координатами. \en A point of a box diagonal with maximal coordinates. public : /// \ru Пустой конструктор. \en The empty constructor. MbCube() { SetEmpty(); } /// \ru Конструктор копирования. \en Copy constructor. MbCube( const MbCube & init ) : pmin( init.pmin ), pmax( init.pmax ) {} /// \ru Конструктор по координатам \en The constructor by coordinates /** \param[in] xmin, ymin, zmin - \ru Координаты точки угла куба с минимальными координатами. \en Coordinates of a box corner point with minimal coordinates. \~ \param[in] xmax, ymax, zmax - \ru Координаты точки угла куба с максимальными координатами. \en Coordinates of a box corner point with maximal coordinates. \~ \param[in] normalize - \ru Нормализовать себя. \en Normalize itself. \~ */ MbCube( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, bool normalize = false ) : pmin( xmin, ymin, zmin ), pmax( xmax, ymax, zmax ) { if ( normalize ) Normalize(); } /// \ru Конструктор по двум точкам. \en The constructor by two points. /** \param[in] p0 - \ru Точка угла куба с минимальными координатами. \en A point of a box corner with minimal coordinates. \~ \param[in] p1 - \ru Точка угла куба с максимальными координатами. \en A point of a box corner with maximal coordinates. \~ \param[in] normalize - \ru Нормализовать себя. \en Normalize itself. \~ */ MbCube( const MbCartPoint3D & p0, const MbCartPoint3D & p1, bool normalize = false ) : pmin( p0 ), pmax( p1 ) { if ( normalize ) Normalize(); } /** \brief \ru Проверка на пустоту. \en The check for emptiness. \details \ru Габаритный параллелепипед считается пустым, если он не содержит ни одной точки 3D-пространства. \en A bounding box is empty if it doesn't contain any points of 3D-space \~ */ bool IsEmpty() const; /// \ru Установить пустым ("вывернутым"). \en Set empty ("reverted"). void SetEmpty(); /// \ru Инициализировать по координатам. \en Initialize by coordinates. /** \param[in] xmin, ymin, zmin - \ru Координаты точки угла куба с минимальными координатами. \en Coordinates of a box corner point with minimal coordinates. \~ \param[in] xmax, ymax, zmax - \ru Координаты точки угла куба с максимальными координатами. \en Coordinates of a box corner point with maximal coordinates. \~ \param[in] normalize - \ru Нормализовать себя. \en Normalize itself. \~ */ void Set( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, bool normalize = false ); /// \ru Инициализировать по двум точкам. \en Initialize by two points. /** \param[in] p0 - \ru Точка угла куба с минимальными координатами. \en A point of a box corner with minimal coordinates. \~ \param[in] p1 - \ru Точка угла куба с максимальными координатами. \en A point of a box corner with maximal coordinates. \~ \param[in] normalize - \ru Нормализовать себя. \en Normalize itself. \~ */ void Set( const MbCartPoint3D & p0, const MbCartPoint3D & p1, bool normalize = false ); /** \ru \name Функции доступа к полям \en \name Functions for access to fields. \{ */ /// \ru Установить минимальную координату по X. \en Set the minimal coordinate by X. void SetXMin( double s ) { pmin.x = s; } /// \ru Установить минимальную координату по Y. \en Set the minimal coordinate by Y. void SetYMin( double s ) { pmin.y = s; } /// \ru Установить минимальную координату по Z. \en Set the minimal coordinate by Z. void SetZMin( double s ) { pmin.z = s; } /// \ru Установить максимальную координату по X. \en Set the maximal coordinate by X. void SetXMax( double s ) { pmax.x = s; } /// \ru Установить максимальную координату по Y. \en Set the maximal coordinate by Y. void SetYMax( double s ) { pmax.y = s; } /// \ru Установить максимальную координату по Z. \en Set the maximal coordinate by Z. void SetZMax( double s ) { pmax.z = s; } /// \ru Дать минимальную координату по X. \en Give the minimal coordinate by X. double GetXMin() const { return pmin.x; } /// \ru Дать минимальную координату по Y. \en Give the minimal coordinate by Y. double GetYMin() const { return pmin.y; } /// \ru Дать минимальную координату по Z. \en Give the minimal coordinate by Z. double GetZMin() const { return pmin.z; } /// \ru Дать максимальную координату по X. \en Give the maximal coordinate by X. double GetXMax() const { return pmax.x; } /// \ru Дать максимальную координату по Y. \en Give the maximal coordinate by Y. double GetYMax() const { return pmax.y; } /// \ru Дать максимальную координату по Z. \en Give the maximal coordinate by Z. double GetZMax() const { return pmax.z; } /** \} */ /// \ru Инициализировать по другому габариту. \en Initialize by another bounding box. void Init( const MbCube & init ) { Set( init.pmin, init.pmax, false ); } /** \brief \ru Инициализировать по двум точкам. \en Initialize by two points. \~ \details \ru Инициализированный куб нормализуется. \en Initialized box is normalized. \~ \param[in] p0 - \ru Точка угла куба с минимальными координатами. \en A point of a box corner with minimal coordinates. \~ \param[in] p1 - \ru Точка угла куба с максимальными координатами. \en A point of a box corner with maximal coordinates. \~ */ void Init( const MbCartPoint3D & p0, const MbCartPoint3D & p1 ) { Set( p0, p1, true ); } /** \brief \ru Добавить габарит. \en Add bounding box. \~ \details \ru Габарит добавляется в локальной системе координат исходного куба. \en A bounding box is added in the local coordinate system of the initial box. \~ \param[in] r - \ru Габарит. \en A bounding box. \~ \param[in] place - \ru Локальная система координат. \en A local coordinate system. \~ */ void AddRect( const MbRect & r, const MbPlacement3D & place ); /** \brief \ru Проекция на плейсмент. \en A projection onto the placement. \~ \details \ru Вычисляет прямоугольник, охватывающий проекцию куба на плейсмент. \en Calculates a rectangle covering a projection of the box onto the placement. \~ \param[in] place - \ru Локальная система координат. \en A local coordinate system. \~ \param[out] rect - \ru Прямоугольник, охватывающий искомую проекцию. \en A rectangle covering a required projection. \~ */ void ProjectionRect( const MbPlacement3D & place, MbRect & rect ) const; /// \ru Вычислить параметрический интервал кривой, охватывающий проекцию куба на кривую. \en Calculate a parametric interval of the curve covering the projection of the box on the curve. void ProjectionRect( const MbCurve3D & curve, bool ext, MbRect1D & rect ) const; /** \ru \name Перегрузка логических операций. \en \name Overload of logical operations. \{ */ /// \ru Присвоить значение. \en Assign a value. void operator = ( const MbCube & ); /// \ru Включить в себя точку. \en Enclose a point. template MbCube & operator |= ( const Point & ); /// \ru Включить в себя габаритный куб. \en Enclose a bounding box. MbCube & operator |= ( const MbCube & ); /// \ru Оператор равенства. \en The equality operator. bool operator == ( const MbCube & ) const; /// \ru Оператор неравенства. \en The inequality operator. bool operator != ( const MbCube & ) const; /** \} */ /// \ru Нормализовать себя. \en Normalize itself. void Normalize (); /** \brief \ru Определить положение куба относительно плоскости. \en Define the box position relative to the plane. \~ \details \ru Определить положение куба относительно плоскости XY локальной системы координат, направление оси Z локальной системы координат при этом не учитывается. \en Define the box position relative to the plane XY of a local coordinate system, the Z axis of the local coordinate system is not taken into account here. \~ \param[in] pl - \ru Локальная система координат, задающая плоскость. \en A local coordinate system which defines a plane. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru iloc_OnItem - куб пересекает плоскость XY локальной системы координат,\n iloc_InItem - куб расположен над плоскостью XY локальной системы координат,\n iloc_OutOfItem - куб расположен под плоскостью XY локальной системы координат. \en Iloc_OnItem - box intersects the XY plane of a local coordinate system,\n iloc_InItem - box is located over the XY plane of a local coordinate system,\n iloc_OutOfItem - box is located under the XY plane of a local coordinate system. \~ */ MbeItemLocation GetLocation( const MbPlacement3D & pl, double eps ) const; /** \brief \ru Определить положение куба относительно трубы. \en Define the box position relative to the tube. \~ \details \ru Определить, расположен ли куб внутри трубы прямоугольного сечения, заданного прямоугольником в плоскости XY локальной системы координат. \en Determine whether the box is inside the tube of rectangular section, given by a rectangle in the XY plane of a local coordinate system. \~ \param[in] place - \ru Локальная система координат, в в плоскости XY которой лежит сечение трубы. \en A local coordinate system in the XY plane of which a tube section is located. \~ \param[in] rect - \ru Прямоугольник, задающая сечение трубы. \en A rectangle which defines a tube section. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если куб расположен внутри трубы. \en Returns true if the box is inside the tube. \~ */ bool InsideLocation( const MbPlacement3D & place, MbRect & rect, double eps ) const; /// \ru Включить в себя точку, заданную как XYZ. \en Enclose a point specified as XYZ. /** \param[in] x, y, z - \ru Координаты точки, которую требуется включить в габарит. \en Coordinates of a point which has to be included in the box. \~ */ void Include( double x, double y, double z ); /// \ru Включить в себя точку. \en Enclose a point. template void Include( const Point & ); /** \ru \name Булевы операции куба с точкой, линией, плоскостью и другим кубом. \en \name The boolean operations of a box with a point, line, plane and another box. \{ */ /// \ru Проверить, лежит ли точка внутри габаритного параллелепипеда. \en Check whether a point is inside the box or not. /** \return \ru true, если лежит. \en Returns true if it is inside. \~ */ template bool Contains( const Point & ) const; /// \ru Проверить, лежит ли точка внутри габаритного параллелепипеда. \en Check whether a point is inside the box or not. /** \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если лежит. \en Returns true if it is inside. \~ */ template bool Contains( const Point &, double eps ) const; /// \ru Проверить, содержит ли один параллелепипед другой. \en Check whether a box is inside another box or not. /** \return \ru true, если данный габаритный параллелепипед содержит другой. \en Returns true if a box contains another. \~ */ bool Contains( const MbCube & ) const; /// \ru Проверить, содержит ли один параллелепипед другой. \en Check whether a box is inside another box or not. /** \return \ru true, если данный габаритный параллелепипед содержит другой. \en Returns true if a box contains another. \~ */ bool Contains( const MbCube &, double eps ) const; /// \ru Пересекается ли габаритный параллелепипед с другим параллелепипедом. \en Whether the box intersects another box or not. /** \param[in] other - \ru Другой параллелепипед. \en Another box. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересекается. \en Returns true if it intersects. \~ */ bool Intersect( const MbCube & other, double eps = (c3d::MIN_RADIUS + c3d::MIN_RADIUS) ) const; /// \ru Пересекается ли куб с плоскостью XY локальной системы координат. \en Whether the box intersects the XY plane of a local coordinate system or not. /** \param[in] pl - \ru Плейсмент, задающий плоскость. \en A placement which defines a plane. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересекается. \en Returns true if it intersects. \~ */ bool Intersect( const MbPlacement3D & pl, double eps = c3d::MIN_RADIUS ) const; /** \brief \ru Пересекается ли куб с линией. \en Whether the box intersects the line or not. \~ \details \ru Линия задается точкой и вектором. \en A line is given by a point and vector. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересекается. \en Returns true if it intersects. \~ */ bool Intersect( const MbCartPoint3D &, const MbVector3D &, double eps = Math::metricRegion ) const; /// \ru Найти пересечение прямой с "поверхностью" куба. \en Find an intersection of a line with the box "surface". /** \param[in] p - \ru Точка на прямой. \en The point on the line. \~ \param[in] axis - \ru Вектор, задающий направление прямой. \en A vector which defines the direction of the line. \~ \param[out] param - \ru Точки пересечения. \en Intersection points. \~ \param[in] delta - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересечение есть, \n false в противном случае. \en Returns true if intersection exists, \n false otherwise. \~ */ bool Intersect( const MbCartPoint3D & p, const MbVector3D & axis, SArray & param, double delta = Math::metricRegion ) const; /// \ru Пересечение куба и окружности. \en The intersection of the box with a circle. /** \param[in] placement - \ru Плейсмент окружности. \en A circle placement. \~ \param[in] radius - \ru Радиус окружности. \en The circle radius. \~ \param[out] param - \ru Точки пересечения. \en Intersection points. \~ \param[in] delta - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересечение есть, \n false в противном случае. \en Returns true if intersection exists, \n false otherwise. \~ */ bool Intersect( const MbPlacement3D & placement, double radius, SArray & param, double delta = Math::metricRegion ) const; /// \ru Куб пересечения двух кубов. \en A box of intersection of two boxes. /** \param[in] cube1, cube2 - \ru Исходные кубы. \en Input boxes. \~ \param[in] eps - \ru Метрическая точность. \en A metric tolerance. \~ \return \ru true, если пересечение есть, \n false в противном случае. \en Returns true if intersection exists, \n false otherwise. \~ */ bool Intersection( const MbCube & cube1, const MbCube & cube2, double eps = c3d::MIN_RADIUS ); /// \ru Куб объединения двух кубов. \en A box of union of two boxes. /** \param[in] cube1, cube2 - \ru Исходные кубы. \en Input boxes. \~ \return \ru false, если итоговый куб пуст, \n true в противном случае. \en Returns false if the result box is empty, \n true otherwise. \~ */ bool Union ( const MbCube & cube1, const MbCube & cube2 ); /** \} */ /// \ru Дать объем куба. \en Give the volume of a box. double GetVolume ( double eps = Math::metricRegion ) const; /// \ru Дать половину площади граней куба. \en Give half of the area of the box faces. double GetSquare ( double eps = Math::metricRegion ) const; /// \ru Дать размер стороны X куба. \en Give the size of the X side of a box. double GetLengthX() const { return pmax.x - pmin.x; } /// \ru Дать размер стороны Y куба. \en Give the size of the Y side of a box. double GetLengthY() const { return pmax.y - pmin.y; } /// \ru Дать размер стороны Z куба. \en Give the size of the Z side of a box. double GetLengthZ() const { return pmax.z - pmin.z; } /// \ru Дать размер диагонали куба. \en Give the size of box diagonal. double GetDiagonal() 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 MbCartPoint3D & point ) const; /// \ru Вычислить квадрат расстояния до точки. \en Calculate the square of distance to a point. double DistanceToPoint2( const MbCartPoint3D & point ) const; /** \brief \ru Вычислить расстояние до куба. \en Calculate the distance to the box. \~ \details \ru Возвращается ноль, если кубы пересекаются или один содержится в другом. \en It returns zero if the boexs 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 MbCube & cube, double eps = Math::metricRegion ) const; /// \ru Расширить куб во все стороны на величину delta. \en Expand the box in all directions on a "delta" amount. void Enlarge ( double delta ); /// \ru Расширить куб во все стороны на соответствующую величину. \en Expand the box in all directions on a corresponding amount. void Enlarge ( double dx, double dy, double dz ); /// \ru Сдвинуть вдоль вектора. \en Translate along a vector. void Move ( const MbVector3D & to ); /// \ru Преобразовать согласно матрице. \en Transform according to the matrix. void Transform( const MbMatrix3D & matrix ); /// \ru Масштабировать. \en Scale. void Scale ( double sx, double sy, double sz ); /// \ru Являются ли объекты равными? \en Determine whether an object is equal? bool IsSame( const MbCube & other, double accuracy ) const; /// \ru Количество координат точки. \en The number of point coordinates. static size_t GetDimension() { return 3; } /// \ru Доступ к минимальной координате по индексу. \en Access to a coordinate by an index. double GetMin( size_t k ) const { return k ? (--k ? pmin.z : pmin.y) : pmin.x; } /// \ru Доступ к максимальной координате по индексу. \en Access to a coordinate by an index. double GetMax( size_t k ) const { return k ? (--k ? pmax.z : pmax.y) : pmax.x; } /// \ru Дать длина по стороне. \en Get side length. double GetSideLength( size_t k ) const { return k ? (--k ? ::fabs(GetLengthZ()) : ::fabs(GetLengthY())) : ::fabs(GetLengthX()); } /// \ru Дать себя. \en Give itself. const MbCube & GetCube() const { return *this; } // \ru Общая нумерация характерных точек куба: \en General numeration of box control points: // \ru 0-7 вершины, 8-19 середины рёбер, 20-25 центры граней \en 0-7 vertices, 8-19 middles of edges, 20-25 centers of faces // Z // | // 4------15------7 // /| /| // 12| 25 14| // / 16 20 / 19 // 5---+--13------6 | // | 22| | 23| // | 0------11--+---3 - Y // 17 / 21 18 / // | 8 24 | 10 // |/ |/ // 1-------9------2 // / // X // \ru Выдать характерные точки куба \en Give control points of the box /// \ru Количество вершин. \en Number of vertices. size_t GetVerticesCount() const { return 8; } /** \brief \ru Выдать все вершины куба. \en Give all vertices of the box. \~ \details \ru Выдать все вершины куба. \en Give all vertices of the box. \~ \param[out] points - \ru Вершины. \en Vertices. \~ \return \ru Число вершин. Ноль, если куб пуст. \en The number of vertices. Null if the box is empty. \~ */ size_t GetVertices( std::vector & points ) const; /// \ru Выдать вершину куба по индексу. \en Get a box vertex by an index. /** \param[in] index - \ru Исходный индекс. 0 <= index <= 7. \en An initial index. 0 <= index <= 7. \~ \param[out] p - \ru Искомая вершина. \en Required vertex. \~ */ void GetVertex( ptrdiff_t index, MbCartPoint3D & p ) const; /// \ru Выдать центр ребра по индексу. \en Give the center of an edge by an index. /** \param[in] index - \ru Исходный индекс. 0 <= index <= 12 (общий номер минус CUBE_VERTEX_COUNT). \en An initial index. 0 <= index <= 12 ("general number" minus CUBE_VERTEX_COUNT). \~ \param[out] p - \ru Координаты центра ребра. \en Coordinates of an edge center. \~ */ void GetEdgeCentre( ptrdiff_t index, MbCartPoint3D & p ) const; /// \ru Выдать центр грани по индексу. \en Give the center of a face by an index. /** \param[in] index - \ru Исходный индекс. 0 <= index <= 5 (общий номер минус CUBE_VERTEX_COUNT минус CUBE_EDGES_COUNT). \en An initial index. 0 <= index <= 5 ("general number" minus CUBE_VERTEX_COUNT minus CUBE_EDGES_COUNT). \~ \param[out] p - \ru Координаты центра ребра. \en Coordinates of an edge center. \~ */ void GetFaceCentre( ptrdiff_t index, MbCartPoint3D & p ) const; /// \ru Выдать центр куба. \en Give the box center. void GetCentre( MbCartPoint3D & p ) const { p.Set( pmax, 0.5, pmin, 0.5 ); } /// \ru Выдать центр куба. \en Give the box center. void GetCenter( MbCartPoint3D & p ) const { p.Set( pmax, 0.5, pmin, 0.5 ); } /// \ru Центр габарита. \en The center of bounding box. MbCartPoint3D Centre() const { return MbCartPoint3D().Set( pmax, 0.5, pmin, 0.5 ); } /** \brief \ru Дать характерную точку куба по ее номеру. \en Give a box control point by its number. \~ \details \ru Общая нумерация характерных точек куба: 0-7 вершины, 8-19 середины рёбер, 20-25 центры граней. \en General numeration of box control points: 0-7 vertices, 8-19 middles of edges, 20-25 centers of faces. \~ \param[in] pIndex - \ru Номер характерных точек. \en A number of control points. \~ \param[out] p - \ru Координаты характерной точки. \en Coordinates of control point. \~ \return \ru false, если куб пуст или индекс принимает недопустимое значение, \n true в противном случае. \en Returns false if the box is empty or the index has an invalid value, \n true otherwise. \~ */ bool GetControlPoint( size_t pIndex, MbCartPoint3D & p ) const; /** \brief \ru Выдать все характерные точки куба. \en Give all control points of the box. \~ \details \ru Все характерные точки куба: 8 вершин, 12 середин рёбер, 6 центров граней. \en All control points of the box: 8 vertices, 12 middles of edges, 6 centers of faces. \~ \param[out] points - \ru Характерные точки. \en Control points. \~ \return \ru Число характерных точек. Ноль, если куб пуст. \en The number of control points. Null if the box is empty. \~ */ size_t GetControlPoints( SArray & points ) const; /// \ru Выдать номер ближайшей характерной точки куба. \en Give the number of the nearest control point of the box. /** \param[in] p - \ru Исходная точка, к которой ищется ближайшая характерная точка куба. \en An initial point for which the nearest control point of the box is searched. \~ \return \ru Номер точки. \en A number of a point. \~ */ size_t GetNearestControlIndex( const MbCartPoint3D & p ) const; /** \brief \ru Дать номер противолежащей точки. \en Give the number of the opposite point. \~ \details \ru Для точки куба с номером index дать номер противолежащей точки, которая может использоваться в качестве фиксированной. \en For a box point with the "index" number give the number of the opposite point, which can be used as fixed. \~ \param[in] index - \ru Номер исходной точки. \en The number of the initial point. \~ \return \ru Номер противолежащей точки. \en A number of the opposite point. \~ */ size_t GetFixedControlIndex ( size_t index ) const; /** \brief \ru Рассчитать матрицу деформации. \en Calculate a deformation matrix. \~ \details \ru Матрица деформации рассчитывается по-новому положению point характерной точки куба с индексом pIndex. \en A deformation matrix is calculated according to the new position of box control point "point" with the index "pIndex". \~ \param[in] pIndex - \ru Номер смещаемой точки (0-7 вершины, 8-19 середины рёбер, 20-25 центры граней). \en A number of a moved point (0-7 vertices, 8-19 middles of edges, 20-25 centers of faces). \~ \param[in] point - \ru Точка, с которой нужно совместить точку куба с номером pIndex. \en A point with which the box point with the "pIndex" number has to be joined. \~ \param[in] fixedPoint - \ru Неподвижная точка преобразования, используется, если useFixed = true. \en A fixed point. It is used if useFixed = true. \~ \param[in] useFixed - \ru Использовать неподвижную точку (true), если useFixed = false, то неподвижной будет противолежащая точка куба. \en Use a fixed point (true); if useFixed = false, then the opposite point of the box will be fixed. \~ \param[in] isotropy - \ru Одинаковые масштабы по осям (true), масштабы, пропорциональны проекциям смещения рассматриваемой точки на стороны куба (false) \en The same scales of the axes (true); the scales are proportional to the shift projections of the considered point on the sides of the box (false) \~ \param[out] matrix - \ru Рассчитанная матрица преобразования. \en Calculated transformation matrix. \~ \return \ru true, если искомая матрица была найдена. \en Returns true if the matrix was found. \~ */ bool CalculateMatrix( size_t pIndex, const MbCartPoint3D & point, const MbCartPoint3D & fixedPoint, bool useFixed, bool isotropy, MbMatrix3D & matrix ) const; public: KNOWN_OBJECTS_RW_REF_OPERATORS_EX_BASE( MbCube, MATH_FUNC_EX ) DECLARE_NEW_DELETE_CLASS( MbCube ) DECLARE_NEW_DELETE_CLASS_EX( MbCube ) }; //------------------------------------------------------------------------------ // \ru Установить пустым ("вывернутым") \en Set empty ("reverted") // --- inline void MbCube::SetEmpty() { pmin.x = pmin.y = pmin.z = MB_MAXDOUBLE; pmax.x = pmax.y = pmax.z = -MB_MAXDOUBLE; } //------------------------------------------------------------------------------ // \ru Проверка на пустоту \en The check for emptiness. // --- inline bool MbCube::IsEmpty() const { return ( pmin.x > pmax.x ) || ( pmin.y > pmax.y ) || ( pmin.z > pmax.z ); } //------------------------------------------------------------------------------ // \ru Установить значения куба \en Set a box values. // --- inline void MbCube::Set( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, bool normalize ) { if ( normalize ) { pmin.x = std_min( xmin, xmax ); pmin.y = std_min( ymin, ymax ); pmin.z = std_min( zmin, zmax ); pmax.x = std_max( xmin, xmax ); pmax.y = std_max( ymin, ymax ); pmax.z = std_max( zmin, zmax ); } else { pmin.x = xmin; pmin.y = ymin; pmin.z = zmin; pmax.x = xmax; pmax.y = ymax; pmax.z = zmax; } } //------------------------------------------------------------------------------ // \ru Установить значения куба \en Set a box values. // --- inline void MbCube::Set( const MbCartPoint3D & p0, const MbCartPoint3D & p1, bool normalize ) { if ( normalize ) { pmin.x = std_min( p0.x, p1.x ); pmin.y = std_min( p0.y, p1.y ); pmin.z = std_min( p0.z, p1.z ); pmax.x = std_max( p0.x, p1.x ); pmax.y = std_max( p0.y, p1.y ); pmax.z = std_max( p0.z, p1.z ); } else { pmin = p0; pmax = p1; } } //------------------------------------------------------------------------------ // \ru Присвоение \en Assignment // --- inline void MbCube::operator = ( const MbCube & other ) { pmin = other.pmin; pmax = other.pmax; } //------------------------------------------------------------------------------ // \ru Включить в себя точку \en Enclose a point. // --- template inline MbCube & MbCube::operator |= ( const Point & p ) { pmin.x = std_min( pmin.x, (double)p.x ); pmin.y = std_min( pmin.y, (double)p.y ); pmin.z = std_min( pmin.z, (double)p.z ); pmax.x = std_max( pmax.x, (double)p.x ); pmax.y = std_max( pmax.y, (double)p.y ); pmax.z = std_max( pmax.z, (double)p.z ); return *this; } //------------------------------------------------------------------------------ // \ru Включить в себя точку,заданную как XYZ \en Enclose a point specified as XYZ. // --- inline void MbCube::Include( double x, double y, double z ) { pmin.x = std_min( pmin.x, x ); pmin.y = std_min( pmin.y, y ); pmin.z = std_min( pmin.z, z ); pmax.x = std_max( pmax.x, x ); pmax.y = std_max( pmax.y, y ); pmax.z = std_max( pmax.z, z ); } //------------------------------------------------------------------------------ // \ru Включить в себя точку \en Enclose a point //--- template inline void MbCube::Include( const Point & pnt ) { Include( pnt.x, pnt.y, pnt.z ); } //------------------------------------------------------------------------------ // \ru Включить в себя габаритный куб \en Enclose a bounding box. // --- inline MbCube & MbCube::operator |= ( const MbCube & other ) { pmin.x = std_min( pmin.x, other.pmin.x ); pmin.y = std_min( pmin.y, other.pmin.y ); pmin.z = std_min( pmin.z, other.pmin.z ); pmax.x = std_max( pmax.x, other.pmax.x ); pmax.y = std_max( pmax.y, other.pmax.y ); pmax.z = std_max( pmax.z, other.pmax.z ); return *this; } //------------------------------------------------------------------------------ // \ru Проверка равенства с другим габаритом. \en The check for equality with another box. // --- inline bool MbCube::operator == ( const MbCube & other ) const { return c3d::EqualPoints( pmin, other.pmin, Math::lengthEpsilon ) && c3d::EqualPoints( pmax, other.pmax, Math::lengthEpsilon ); } //------------------------------------------------------------------------------ // \ru Проверка неравенства с другим кубом. \en The check for inequality with another box. // --- inline bool MbCube::operator != ( const MbCube & other) const { return !( other == *this ); } //------------------------------------------------------------------------------ // \ru Проверка на то, что заданная точка лежит внутри куба \en Check whether a given point is inside the box or not // --- template inline bool MbCube::Contains( const Point & p ) const { return ( ( (double)p.x >= pmin.x ) && ( (double)p.x <= pmax.x ) && ( (double)p.y >= pmin.y ) && ( (double)p.y <= pmax.y ) && ( (double)p.z >= pmin.z ) && ( (double)p.z <= pmax.z ) ); } //------------------------------------------------------------------------------- // \ru Проверка на то, что заданная точка лежит внутри габарита. \en Check whether a given point is inside the box or not. // --- template inline bool MbCube::Contains( const Point & p, double eps ) const { return ( ((double)p.x > (pmin.x - eps)) && ((double)p.x < (pmax.x + eps)) && ((double)p.y > (pmin.y - eps)) && ((double)p.y < (pmax.y + eps)) && ((double)p.z > (pmin.z - eps)) && ((double)p.z < (pmax.z + eps)) ); } //------------------------------------------------------------------------------ /// \ru Проверить, содержит ли один параллелепипед другой. \en Check whether a box is inside another box or not. //--- inline bool MbCube::Contains( const MbCube & box ) const { return Contains( box.pmin ) && Contains( box.pmax ); } //------------------------------------------------------------------------------ /// \ru Проверить, содержит ли один параллелепипед другой. \en Check whether a box is inside another box or not. //--- inline bool MbCube::Contains( const MbCube & box, double eps ) const { return Contains( box.pmin, eps ) && Contains( box.pmax, eps ); } //------------------------------------------------------------------------------ // \ru Нормализовать себя \en Normalize itself // --- inline void MbCube::Normalize() { double tmp; if ( pmin.x > pmax.x ) { tmp = pmin.x; pmin.x = pmax.x; pmax.x = tmp; } if ( pmin.y > pmax.y ) { tmp = pmin.y; pmin.y = pmax.y; pmax.y = tmp; } if ( pmin.z > pmax.z ) { tmp = pmin.z; pmin.z = pmax.z; pmax.z = tmp; } } //------------------------------------------------------------------------------ // \ru Расширить куб во все стороны \en Expand the box in all directions // --- inline void MbCube::Enlarge( double delta ) { pmin.x -= delta; pmin.y -= delta; pmin.z -= delta; pmax.x += delta; pmax.y += delta; pmax.z += delta; } //------------------------------------------------------------------------------ // \ru Расширить куб во все стороны. \en Expand the box in all directions // --- inline void MbCube::Enlarge( double dx, double dy, double dz ) { pmin.x -= dx; pmin.y -= dy; pmin.z -= dz; pmax.x += dx; pmax.y += dy; pmax.z += dz; } //------------------------------------------------------------------------------ // \ru Сдвиг \en Translation // --- inline void MbCube::Move( const MbVector3D & to ) { if ( !IsEmpty() ) { pmin.Move( to ); pmax.Move( to ); } } //------------------------------------------------------------------------------ // \ru Расстояние до точки \en The distance to a point // --- inline double MbCube::DistanceToPoint( const MbCartPoint3D & pnt ) const { double dx = std_max( pmin.x - pnt.x, pnt.x - pmax.x ); double dy = std_max( pmin.y - pnt.y, pnt.y - pmax.y ); double dz = std_max( pmin.z - pnt.z, pnt.z - pmax.z ); double dd = std_max( dx, dy ); return std_max( dd, dz ); } //------------------------------------------------------------------------------ // \ru Квадрат расстояния до точки \en The square of distance to a point // --- inline double MbCube::DistanceToPoint2( const MbCartPoint3D & pnt ) const { double dx = std_min( 0., std_min( pnt.x - pmin.x, pmax.x - pnt.x ) ); double dy = std_min( 0., std_min( pnt.y - pmin.y, pmax.y - pnt.y ) ); double dz = std_min( 0., std_min( pnt.z - pmin.z, pmax.z - pnt.z ) ); return dx * dx + dy * dy + dz * dz; } #endif // __MB_CUBE_H