| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #ifndef BASE_BOUNDBOX_H
|
| | #define BASE_BOUNDBOX_H
|
| |
|
| | #include <array>
|
| | #include <limits>
|
| | #include "Matrix.h"
|
| | #include "Tools2D.h"
|
| | #include "ViewProj.h"
|
| |
|
| |
|
| | namespace Base
|
| | {
|
| |
|
| | class ViewProjMethod;
|
| |
|
| |
|
| | template<class Precision>
|
| | class BoundBox3
|
| | {
|
| |
|
| | static bool isOnRayW(Precision min, Precision max, Precision val);
|
| | static bool isOnRayS(Precision min, Precision max, Precision val);
|
| |
|
| | public:
|
| | using num_type = Precision;
|
| | using traits_type = float_traits<num_type>;
|
| |
|
| |
|
| |
|
| | Precision MinX;
|
| | Precision MinY;
|
| | Precision MinZ;
|
| | Precision MaxX;
|
| | Precision MaxY;
|
| | Precision MaxZ;
|
| |
|
| |
|
| |
|
| | inline explicit BoundBox3(
|
| | Precision fMinX = std::numeric_limits<Precision>::max(),
|
| | Precision fMinY = std::numeric_limits<Precision>::max(),
|
| | Precision fMinZ = std::numeric_limits<Precision>::max(),
|
| | Precision fMaxX = -std::numeric_limits<Precision>::max(),
|
| | Precision fMaxY = -std::numeric_limits<Precision>::max(),
|
| | Precision fMaxZ = -std::numeric_limits<Precision>::max()
|
| | );
|
| | BoundBox3(const BoundBox3<Precision>& rcBB) = default;
|
| | BoundBox3(BoundBox3<Precision>&& rcBB) noexcept = default;
|
| |
|
| | inline BoundBox3(const Vector3<Precision>* pclVect, std::size_t ulCt);
|
| |
|
| | |
| | |
| |
|
| | BoundBox3(const Vector3<Precision>& point, Precision distance);
|
| | ~BoundBox3();
|
| |
|
| |
|
| | inline BoundBox3<Precision>& operator=(const BoundBox3<Precision>& rcBound) = default;
|
| | inline BoundBox3<Precision>& operator=(BoundBox3<Precision>&& rcBound) noexcept = default;
|
| |
|
| |
|
| |
|
| |
|
| | inline bool Intersect(const BoundBox3<Precision>& rcBB) const;
|
| |
|
| | inline bool operator&&(const BoundBox3<Precision>& rcBB) const;
|
| |
|
| | inline bool Intersect(const BoundBox2d& rcBB) const;
|
| |
|
| | inline bool operator&&(const BoundBox2d& rcBB) const;
|
| | |
| | |
| |
|
| | BoundBox3<Precision> Intersected(const BoundBox3<Precision>& rcBB) const;
|
| |
|
| | BoundBox3<Precision> United(const BoundBox3<Precision>& rcBB) const;
|
| |
|
| | inline void Add(const Vector3<Precision>& rclVect);
|
| |
|
| | inline void Add(const BoundBox3<Precision>& rcBB);
|
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| |
|
| | inline bool IsInBox(const Vector3<Precision>& rcVct) const;
|
| | |
| | |
| |
|
| | inline bool IsInBox(const BoundBox3<Precision>& rcBB) const;
|
| | |
| | |
| |
|
| | inline bool IsInBox(const BoundBox2d& rcbb) const;
|
| |
|
| | bool IsValid() const;
|
| |
|
| |
|
| | enum OCTANT
|
| | {
|
| | OCT_LDB = 0,
|
| | OCT_RDB,
|
| | OCT_LUB,
|
| | OCT_RUB,
|
| | OCT_LDF,
|
| | OCT_RDF,
|
| | OCT_LUF,
|
| | OCT_RUF
|
| | };
|
| | bool GetOctantFromVector(const Vector3<Precision>& rclVct, OCTANT& rclOctant) const;
|
| | BoundBox3<Precision> CalcOctant(typename BoundBox3<Precision>::OCTANT Octant) const;
|
| |
|
| | enum SIDE
|
| | {
|
| | LEFT = 0,
|
| | RIGHT = 1,
|
| | TOP = 2,
|
| | BOTTOM = 3,
|
| | FRONT = 4,
|
| | BACK = 5,
|
| | INVALID = 255
|
| | };
|
| | enum CORNER
|
| | {
|
| | TLB = 0,
|
| | TLF = 1,
|
| | TRF = 2,
|
| | TRB = 3,
|
| | BLB = 4,
|
| | BLF = 5,
|
| | BRF = 6,
|
| | BRB = 7,
|
| | };
|
| | enum EDGE
|
| | {
|
| | TLB_TLF = 0,
|
| | TLF_TRF = 1,
|
| | TRF_TRB = 2,
|
| | TRB_TLB = 3,
|
| | BLB_BLF = 4,
|
| | BLF_BRF = 5,
|
| | BRF_BRB = 6,
|
| | BRB_BLB = 7,
|
| | TLB_BLB = 8,
|
| | TLF_BLF = 9,
|
| | TRF_BRF = 10,
|
| | TRB_BRB = 11
|
| | };
|
| |
|
| | |
| | |
| |
|
| | inline Vector3<Precision> CalcPoint(unsigned short usPoint) const;
|
| |
|
| | void CalcPlane(unsigned short usPlane, Vector3<Precision>& rBase, Vector3<Precision>& rNormal) const;
|
| | |
| |
|
| | bool CalcEdge(unsigned short usEdge, Vector3<Precision>& rcP0, Vector3<Precision>& rcP1) const;
|
| | |
| | |
| | |
| |
|
| | bool IntersectionPoint(
|
| | const Vector3<Precision>& rcVct,
|
| | const Vector3<Precision>& rcVctDir,
|
| | Vector3<Precision>& cVctRes,
|
| | Precision epsilon
|
| | ) const;
|
| |
|
| | bool IsCutLine(
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Precision fTolerance = 0.0F
|
| | ) const;
|
| | |
| | |
| |
|
| | inline bool IsCutPlane(const Vector3<Precision>& rclBase, const Vector3<Precision>& rclNormal) const;
|
| |
|
| | bool IntersectWithLine(
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Vector3<Precision>& rcP0,
|
| | Vector3<Precision>& rcP1
|
| | ) const;
|
| |
|
| | bool IntersectPlaneWithLine(
|
| | unsigned short usSide,
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Vector3<Precision>& rcP0
|
| | ) const;
|
| |
|
| | typename BoundBox3<Precision>::SIDE GetSideFromRay(
|
| | const Vector3<Precision>& rclPt,
|
| | const Vector3<Precision>& rclDir
|
| | ) const;
|
| |
|
| | typename BoundBox3<Precision>::SIDE GetSideFromRay(
|
| | const Vector3<Precision>& rclPt,
|
| | const Vector3<Precision>& rclDir,
|
| | Vector3<Precision>& rcInt
|
| | ) const;
|
| |
|
| | |
| | |
| |
|
| | Vector3<Precision> ClosestPoint(const Vector3<Precision>& rclPt) const;
|
| |
|
| | BoundBox2d ProjectBox(const ViewProjMethod* proj) const;
|
| | |
| | |
| |
|
| | BoundBox3<Precision> Transformed(const Matrix4D& mat) const;
|
| |
|
| |
|
| | inline Vector3<Precision> GetCenter() const;
|
| |
|
| | inline Vector3<Precision> GetMinimum() const;
|
| |
|
| | inline Vector3<Precision> GetMaximum() const;
|
| | |
| | |
| |
|
| | inline Precision CalcDiagonalLength() const;
|
| | void SetVoid();
|
| |
|
| |
|
| | inline void Enlarge(Precision fLen);
|
| |
|
| | inline void Shrink(Precision fLen);
|
| |
|
| |
|
| | inline Precision LengthX() const;
|
| |
|
| | inline Precision LengthY() const;
|
| |
|
| | inline Precision LengthZ() const;
|
| |
|
| | inline Precision Volume() const;
|
| |
|
| | inline void MoveX(Precision value);
|
| |
|
| | inline void MoveY(Precision value);
|
| |
|
| | inline void MoveZ(Precision value);
|
| |
|
| | inline void ScaleX(Precision value);
|
| |
|
| | inline void ScaleY(Precision value);
|
| |
|
| | inline void ScaleZ(Precision value);
|
| |
|
| |
|
| | void Print(std::ostream&) const;
|
| | };
|
| |
|
| |
|
| | template<class Precision>
|
| | bool BoundBox3<Precision>::isOnRayW(Precision min, Precision max, Precision val)
|
| | {
|
| |
|
| | return ((min <= val) && (val <= max));
|
| | }
|
| |
|
| | template<class Precision>
|
| | bool BoundBox3<Precision>::isOnRayS(Precision min, Precision max, Precision val)
|
| | {
|
| |
|
| | return ((min <= val) && (val < max));
|
| | }
|
| |
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision>::BoundBox3(
|
| | Precision fMinX,
|
| | Precision fMinY,
|
| | Precision fMinZ,
|
| | Precision fMaxX,
|
| | Precision fMaxY,
|
| | Precision fMaxZ
|
| | )
|
| | : MinX(fMinX)
|
| | , MinY(fMinY)
|
| | , MinZ(fMinZ)
|
| | , MaxX(fMaxX)
|
| | , MaxY(fMaxY)
|
| | , MaxZ(fMaxZ)
|
| | {}
|
| |
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision>::BoundBox3(const Vector3<Precision>* pclVect, std::size_t ulCt)
|
| | : MinX(std::numeric_limits<Precision>::max())
|
| | , MinY(std::numeric_limits<Precision>::max())
|
| | , MinZ(std::numeric_limits<Precision>::max())
|
| | , MaxX(-std::numeric_limits<Precision>::max())
|
| | , MaxY(-std::numeric_limits<Precision>::max())
|
| | , MaxZ(-std::numeric_limits<Precision>::max())
|
| | {
|
| | const Vector3<Precision>* pI = nullptr;
|
| | const Vector3<Precision>* pEnd = pclVect + ulCt;
|
| | for (pI = pclVect; pI < pEnd; ++pI) {
|
| | MinX = std::min<Precision>(MinX, pI->x);
|
| | MinY = std::min<Precision>(MinY, pI->y);
|
| | MinZ = std::min<Precision>(MinZ, pI->z);
|
| | MaxX = std::max<Precision>(MaxX, pI->x);
|
| | MaxY = std::max<Precision>(MaxY, pI->y);
|
| | MaxZ = std::max<Precision>(MaxZ, pI->z);
|
| | }
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision>::BoundBox3(const Vector3<Precision>& point, Precision distance)
|
| | : MinX(point.x - distance)
|
| | , MinY(point.y - distance)
|
| | , MinZ(point.z - distance)
|
| | , MaxX(point.x + distance)
|
| | , MaxY(point.y + distance)
|
| | , MaxZ(point.z + distance)
|
| | {}
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision>::~BoundBox3() = default;
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::Intersect(const BoundBox3<Precision>& rcBB) const
|
| | {
|
| | if (rcBB.MaxX < this->MinX || rcBB.MinX > this->MaxX) {
|
| | return false;
|
| | }
|
| | if (rcBB.MaxY < this->MinY || rcBB.MinY > this->MaxY) {
|
| | return false;
|
| | }
|
| | if (rcBB.MaxZ < this->MinZ || rcBB.MinZ > this->MaxZ) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | bool BoundBox3<Precision>::operator&&(const BoundBox3<Precision>& rcBB) const
|
| | {
|
| | return Intersect(rcBB);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::Intersect(const BoundBox2d& rcBB) const
|
| | {
|
| | if (rcBB.MaxX < this->MinX || rcBB.MinX > this->MaxX) {
|
| | return false;
|
| | }
|
| | if (rcBB.MaxY < this->MinY || rcBB.MinY > this->MaxY) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::operator&&(const BoundBox2d& rcBB) const
|
| | {
|
| | return Intersect(rcBB);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision> BoundBox3<Precision>::Intersected(const BoundBox3<Precision>& rcBB) const
|
| | {
|
| | BoundBox3<Precision> cBBRes;
|
| |
|
| | cBBRes.MinX = std::max<Precision>(MinX, rcBB.MinX);
|
| | cBBRes.MaxX = std::min<Precision>(MaxX, rcBB.MaxX);
|
| | cBBRes.MinY = std::max<Precision>(MinY, rcBB.MinY);
|
| | cBBRes.MaxY = std::min<Precision>(MaxY, rcBB.MaxY);
|
| | cBBRes.MinZ = std::max<Precision>(MinZ, rcBB.MinZ);
|
| | cBBRes.MaxZ = std::min<Precision>(MaxZ, rcBB.MaxZ);
|
| |
|
| | return cBBRes;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision> BoundBox3<Precision>::United(const BoundBox3<Precision>& rcBB) const
|
| | {
|
| | BoundBox3<Precision> cBBRes;
|
| |
|
| | cBBRes.MinX = std::min<Precision>(MinX, rcBB.MinX);
|
| | cBBRes.MaxX = std::max<Precision>(MaxX, rcBB.MaxX);
|
| | cBBRes.MinY = std::min<Precision>(MinY, rcBB.MinY);
|
| | cBBRes.MaxY = std::max<Precision>(MaxY, rcBB.MaxY);
|
| | cBBRes.MinZ = std::min<Precision>(MinZ, rcBB.MinZ);
|
| | cBBRes.MaxZ = std::max<Precision>(MaxZ, rcBB.MaxZ);
|
| |
|
| | return cBBRes;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::Add(const Vector3<Precision>& rclVect)
|
| | {
|
| | this->MinX = std::min<Precision>(this->MinX, rclVect.x);
|
| | this->MinY = std::min<Precision>(this->MinY, rclVect.y);
|
| | this->MinZ = std::min<Precision>(this->MinZ, rclVect.z);
|
| | this->MaxX = std::max<Precision>(this->MaxX, rclVect.x);
|
| | this->MaxY = std::max<Precision>(this->MaxY, rclVect.y);
|
| | this->MaxZ = std::max<Precision>(this->MaxZ, rclVect.z);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::Add(const BoundBox3<Precision>& rcBB)
|
| | {
|
| | this->MinX = std::min<Precision>(this->MinX, rcBB.MinX);
|
| | this->MaxX = std::max<Precision>(this->MaxX, rcBB.MaxX);
|
| | this->MinY = std::min<Precision>(this->MinY, rcBB.MinY);
|
| | this->MaxY = std::max<Precision>(this->MaxY, rcBB.MaxY);
|
| | this->MinZ = std::min<Precision>(this->MinZ, rcBB.MinZ);
|
| | this->MaxZ = std::max<Precision>(this->MaxZ, rcBB.MaxZ);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsInBox(const Vector3<Precision>& rcVct) const
|
| | {
|
| | if (rcVct.x < this->MinX || rcVct.x > this->MaxX) {
|
| | return false;
|
| | }
|
| | if (rcVct.y < this->MinY || rcVct.y > this->MaxY) {
|
| | return false;
|
| | }
|
| | if (rcVct.z < this->MinZ || rcVct.z > this->MaxZ) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsInBox(const BoundBox3<Precision>& rcBB) const
|
| | {
|
| | if (rcBB.MinX < this->MinX || rcBB.MaxX > this->MaxX) {
|
| | return false;
|
| | }
|
| | if (rcBB.MinY < this->MinY || rcBB.MaxY > this->MaxY) {
|
| | return false;
|
| | }
|
| | if (rcBB.MinZ < this->MinZ || rcBB.MaxZ > this->MaxZ) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsInBox(const BoundBox2d& rcBB) const
|
| | {
|
| | if (rcBB.MinX < this->MinX || rcBB.MaxX > this->MaxX) {
|
| | return false;
|
| | }
|
| | if (rcBB.MinY < this->MinY || rcBB.MaxY > this->MaxY) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsValid() const
|
| | {
|
| | return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ));
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::GetOctantFromVector(
|
| | const Vector3<Precision>& rclVct,
|
| | OCTANT& rclOctant
|
| | ) const
|
| | {
|
| | if (!IsInBox(rclVct)) {
|
| | return false;
|
| | }
|
| |
|
| | unsigned short usNdx = 0;
|
| | if (isOnRayS((MinX + MaxX) / 2, MaxX, rclVct.x)) {
|
| | usNdx |= 1;
|
| | }
|
| | if (isOnRayS((MinY + MaxY) / 2, MaxY, rclVct.y)) {
|
| | usNdx |= 2;
|
| | }
|
| | if (isOnRayS((MinZ + MaxZ) / 2, MaxZ, rclVct.z)) {
|
| | usNdx |= 4;
|
| | }
|
| | rclOctant = static_cast<OCTANT>(usNdx);
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision> BoundBox3<Precision>::CalcOctant(
|
| | typename BoundBox3<Precision>::OCTANT Octant
|
| | ) const
|
| | {
|
| | BoundBox3<Precision> cOct(*this);
|
| |
|
| | switch (Octant) {
|
| | case OCT_LDB:
|
| | cOct.MaxX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MaxY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MaxZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_RDB:
|
| | cOct.MinX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MaxY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MaxZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_LUB:
|
| | cOct.MaxX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MinY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MaxZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_RUB:
|
| | cOct.MinX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MinY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MaxZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_LDF:
|
| | cOct.MaxX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MaxY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MinZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_RDF:
|
| | cOct.MinX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MaxY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MinZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_LUF:
|
| | cOct.MaxX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MinY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MinZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| |
|
| | case OCT_RUF:
|
| | cOct.MinX = (cOct.MinX + cOct.MaxX) / 2;
|
| | cOct.MinY = (cOct.MinY + cOct.MaxY) / 2;
|
| | cOct.MinZ = (cOct.MinZ + cOct.MaxZ) / 2;
|
| | break;
|
| | }
|
| | return cOct;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Vector3<Precision> BoundBox3<Precision>::CalcPoint(unsigned short usPoint) const
|
| | {
|
| | switch (usPoint) {
|
| | case TLB:
|
| | return Vector3<Precision>(MinX, MinY, MaxZ);
|
| | case TLF:
|
| | return Vector3<Precision>(MaxX, MinY, MaxZ);
|
| | case TRF:
|
| | return Vector3<Precision>(MaxX, MaxY, MaxZ);
|
| | case TRB:
|
| | return Vector3<Precision>(MinX, MaxY, MaxZ);
|
| | case BLB:
|
| | return Vector3<Precision>(MinX, MinY, MinZ);
|
| | case BLF:
|
| | return Vector3<Precision>(MaxX, MinY, MinZ);
|
| | case BRF:
|
| | return Vector3<Precision>(MaxX, MaxY, MinZ);
|
| | case BRB:
|
| | return Vector3<Precision>(MinX, MaxY, MinZ);
|
| | }
|
| |
|
| | return Vector3<Precision>();
|
| | }
|
| |
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::CalcPlane(
|
| | unsigned short usPlane,
|
| | Vector3<Precision>& rBase,
|
| | Vector3<Precision>& rNormal
|
| | ) const
|
| |
|
| | {
|
| | switch (usPlane) {
|
| | case LEFT:
|
| | rBase.Set(MinX, MinY, MaxZ);
|
| | rNormal.Set(1.0F, 0.0F, 0.0F);
|
| | break;
|
| |
|
| | case RIGHT:
|
| | rBase.Set(MaxX, MinY, MaxZ);
|
| | rNormal.Set(1.0F, 0.0F, 0.0F);
|
| | break;
|
| |
|
| | case TOP:
|
| | rBase.Set(MinX, MaxY, MaxZ);
|
| | rNormal.Set(0.0F, 1.0F, 0.0F);
|
| | break;
|
| |
|
| | case BOTTOM:
|
| | rBase.Set(MinX, MinY, MaxZ);
|
| | rNormal.Set(0.0F, 1.0F, 0.0F);
|
| | break;
|
| |
|
| | case FRONT:
|
| | rBase.Set(MinX, MinY, MaxZ);
|
| | rNormal.Set(0.0F, 0.0F, 1.0F);
|
| | break;
|
| |
|
| | case BACK:
|
| | rBase.Set(MinX, MinY, MinZ);
|
| | rNormal.Set(0.0F, 0.0F, 1.0F);
|
| | break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::CalcEdge(
|
| | unsigned short usEdge,
|
| | Vector3<Precision>& rcP0,
|
| | Vector3<Precision>& rcP1
|
| | ) const
|
| | {
|
| | switch (usEdge) {
|
| | case TLB_TLF:
|
| | rcP0 = CalcPoint(TLB);
|
| | rcP1 = CalcPoint(TLF);
|
| | break;
|
| | case TLF_TRF:
|
| | rcP0 = CalcPoint(TLF);
|
| | rcP1 = CalcPoint(TRF);
|
| | break;
|
| | case TRF_TRB:
|
| | rcP0 = CalcPoint(TRF);
|
| | rcP1 = CalcPoint(TRB);
|
| | break;
|
| | case TRB_TLB:
|
| | rcP0 = CalcPoint(TRB);
|
| | rcP1 = CalcPoint(TLB);
|
| | break;
|
| | case BLB_BLF:
|
| | rcP0 = CalcPoint(BLB);
|
| | rcP1 = CalcPoint(BLF);
|
| | break;
|
| | case BLF_BRF:
|
| | rcP0 = CalcPoint(BLF);
|
| | rcP1 = CalcPoint(BRF);
|
| | break;
|
| | case BRF_BRB:
|
| | rcP0 = CalcPoint(BRF);
|
| | rcP1 = CalcPoint(BRB);
|
| | break;
|
| | case BRB_BLB:
|
| | rcP0 = CalcPoint(BRB);
|
| | rcP1 = CalcPoint(BLB);
|
| | break;
|
| | case TLB_BLB:
|
| | rcP0 = CalcPoint(TLB);
|
| | rcP1 = CalcPoint(BLB);
|
| | break;
|
| | case TLF_BLF:
|
| | rcP0 = CalcPoint(TLF);
|
| | rcP1 = CalcPoint(BLF);
|
| | break;
|
| | case TRF_BRF:
|
| | rcP0 = CalcPoint(TRF);
|
| | rcP1 = CalcPoint(BRF);
|
| | break;
|
| | case TRB_BRB:
|
| | rcP0 = CalcPoint(TRB);
|
| | rcP1 = CalcPoint(BRB);
|
| | break;
|
| | default:
|
| | return false;
|
| | }
|
| |
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IntersectionPoint(
|
| | const Vector3<Precision>& rcVct,
|
| | const Vector3<Precision>& rcVctDir,
|
| | Vector3<Precision>& cVctRes,
|
| | Precision epsilon
|
| | ) const
|
| | {
|
| | const unsigned short num = 6;
|
| | bool rc = false;
|
| | BoundBox3<Precision> cCmpBound(*this);
|
| |
|
| |
|
| | cCmpBound.Enlarge(epsilon);
|
| |
|
| |
|
| | if (cCmpBound.IsInBox(rcVct)) {
|
| |
|
| | for (unsigned short i = 0; (i < num) && (!rc); i++) {
|
| | rc = IntersectPlaneWithLine(i, rcVct, rcVctDir, cVctRes);
|
| |
|
| | if (!cCmpBound.IsInBox(cVctRes)) {
|
| | rc = false;
|
| | }
|
| |
|
| | if (rc) {
|
| |
|
| |
|
| |
|
| | rc = ((cVctRes - rcVct) * rcVctDir) >= 0.0;
|
| | }
|
| | }
|
| | }
|
| |
|
| | return rc;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsCutLine(
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Precision fTolerance
|
| | ) const
|
| | {
|
| | const unsigned short num = 6;
|
| | Precision fDist;
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | fDist = (rcDir % (GetCenter() - rcBase)).Length() / rcDir.Length();
|
| |
|
| | if (fDist > (CalcDiagonalLength() + fTolerance)) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| | Vector3<Precision> clVectRes;
|
| |
|
| |
|
| | for (unsigned short i = 0; i < num; i++) {
|
| | if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) {
|
| |
|
| | switch (i) {
|
| | case LEFT:
|
| | case RIGHT:
|
| | if ((isOnRayW(MinY - fTolerance, MaxY + fTolerance, clVectRes.y)
|
| | && isOnRayW(MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))) {
|
| | return true;
|
| | }
|
| | break;
|
| | case TOP:
|
| | case BOTTOM:
|
| | if ((isOnRayW(MinX - fTolerance, MaxX + fTolerance, clVectRes.x)
|
| | && isOnRayW(MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))) {
|
| | return true;
|
| | }
|
| | break;
|
| | case FRONT:
|
| | case BACK:
|
| | if ((isOnRayW(MinX - fTolerance, MaxX + fTolerance, clVectRes.x)
|
| | && isOnRayW(MinY - fTolerance, MaxY + fTolerance, clVectRes.y))) {
|
| | return true;
|
| | }
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IsCutPlane(
|
| | const Vector3<Precision>& rclBase,
|
| | const Vector3<Precision>& rclNormal
|
| | ) const
|
| | {
|
| | const unsigned short num = 8;
|
| | if (fabs(GetCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength()) {
|
| | Precision fD = CalcPoint(CORNER::TLB).DistanceToPlane(rclBase, rclNormal);
|
| | for (unsigned short i = 1; i < num; i++) {
|
| | if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) <= 0.0F) {
|
| | return true;
|
| | }
|
| | }
|
| | }
|
| | return false;
|
| | }
|
| |
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IntersectWithLine(
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Vector3<Precision>& rcP0,
|
| | Vector3<Precision>& rcP1
|
| | ) const
|
| |
|
| | {
|
| | const unsigned short num = 6;
|
| | Vector3<Precision> clVectRes;
|
| | std::array<Vector3<Precision>, num> clVect;
|
| | unsigned short numIntersect = 0;
|
| |
|
| | auto checkIntersect = [&](Base::Vector3<Precision> p1, Base::Vector3<Precision> p2) {
|
| | if (isOnRayS(p1.x, p1.y, p1.z) && isOnRayS(p2.x, p2.y, p2.z)) {
|
| | clVect[numIntersect] = clVectRes;
|
| | numIntersect++;
|
| | }
|
| | };
|
| |
|
| |
|
| | for (unsigned short i = 0; i < num; i++) {
|
| | if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) {
|
| |
|
| | switch (i) {
|
| | case LEFT:
|
| | case RIGHT:
|
| | checkIntersect(
|
| | Vector3<Precision> {MinY, MaxY, clVectRes.y},
|
| | Vector3<Precision> {MinZ, MaxZ, clVectRes.z}
|
| | );
|
| | break;
|
| | case TOP:
|
| | case BOTTOM:
|
| | checkIntersect(
|
| | Vector3<Precision> {MinX, MaxX, clVectRes.x},
|
| | Vector3<Precision> {MinZ, MaxZ, clVectRes.z}
|
| | );
|
| | break;
|
| | case FRONT:
|
| | case BACK:
|
| | checkIntersect(
|
| | Vector3<Precision> {MinX, MaxX, clVectRes.x},
|
| | Vector3<Precision> {MinY, MaxY, clVectRes.y}
|
| | );
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (numIntersect == 2) {
|
| | rcP0 = clVect[0];
|
| | rcP1 = clVect[1];
|
| | return true;
|
| | }
|
| |
|
| | if (numIntersect > 2) {
|
| | for (unsigned short i = 1; i < numIntersect; i++) {
|
| | if (clVect[i] != clVect[0]) {
|
| | rcP0 = clVect[0];
|
| | rcP1 = clVect[i];
|
| | return true;
|
| | }
|
| | }
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| |
|
| | template<class Precision>
|
| | inline bool BoundBox3<Precision>::IntersectPlaneWithLine(
|
| | unsigned short usSide,
|
| | const Vector3<Precision>& rcBase,
|
| | const Vector3<Precision>& rcDir,
|
| | Vector3<Precision>& rcP0
|
| | ) const
|
| |
|
| | {
|
| | Precision value;
|
| | Vector3<Precision> cBase;
|
| | Vector3<Precision> cNormal;
|
| | Vector3<Precision> cDir(rcDir);
|
| | CalcPlane(usSide, cBase, cNormal);
|
| |
|
| | if ((cNormal * cDir) == 0.0F) {
|
| | return false;
|
| | }
|
| |
|
| | value = (cNormal * (cBase - rcBase)) / (cNormal * cDir);
|
| | cDir.Scale(value, value, value);
|
| | rcP0 = rcBase + cDir;
|
| | return true;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline typename BoundBox3<Precision>::SIDE BoundBox3<Precision>::GetSideFromRay(
|
| | const Vector3<Precision>& rclPt,
|
| | const Vector3<Precision>& rclDir
|
| | ) const
|
| | {
|
| | Vector3<Precision> cIntersection;
|
| | return GetSideFromRay(rclPt, rclDir, cIntersection);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline typename BoundBox3<Precision>::SIDE BoundBox3<Precision>::GetSideFromRay(
|
| | const Vector3<Precision>& rclPt,
|
| | const Vector3<Precision>& rclDir,
|
| | Vector3<Precision>& rcInt
|
| | ) const
|
| | {
|
| | Vector3<Precision> cP0;
|
| | Vector3<Precision> cP1;
|
| | if (!IntersectWithLine(rclPt, rclDir, cP0, cP1)) {
|
| | return INVALID;
|
| | }
|
| |
|
| | Vector3<Precision> cOut;
|
| |
|
| | if ((cP1 - cP0) * rclDir > 0) {
|
| | cOut = cP1;
|
| | }
|
| | else {
|
| | cOut = cP0;
|
| | }
|
| |
|
| | rcInt = cOut;
|
| |
|
| | Precision fMax = 1.0e-3F;
|
| | SIDE tSide = INVALID;
|
| |
|
| | if (fabs(cOut.x - MinX) < fMax) {
|
| | fMax = Precision(fabs(cOut.x - MinX));
|
| | tSide = LEFT;
|
| | }
|
| |
|
| | if (fabs(cOut.x - MaxX) < fMax) {
|
| | fMax = Precision(fabs(cOut.x - MaxX));
|
| | tSide = RIGHT;
|
| | }
|
| |
|
| | if (fabs(cOut.y - MinY) < fMax) {
|
| | fMax = Precision(fabs(cOut.y - MinY));
|
| | tSide = BOTTOM;
|
| | }
|
| |
|
| | if (fabs(cOut.y - MaxY) < fMax) {
|
| | fMax = Precision(fabs(cOut.y - MaxY));
|
| | tSide = TOP;
|
| | }
|
| |
|
| | if (fabs(cOut.z - MinZ) < fMax) {
|
| | fMax = Precision(fabs(cOut.z - MinZ));
|
| | tSide = FRONT;
|
| | }
|
| |
|
| | if (fabs(cOut.z - MaxZ) < fMax) {
|
| | fMax = Precision(fabs(cOut.z - MaxZ));
|
| | tSide = BACK;
|
| | }
|
| |
|
| | return tSide;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Vector3<Precision> BoundBox3<Precision>::ClosestPoint(const Vector3<Precision>& rclPt) const
|
| | {
|
| | Vector3<Precision> closest = rclPt;
|
| |
|
| | Vector3<Precision> center = GetCenter();
|
| | Precision devx = closest.x - center.x;
|
| | Precision devy = closest.y - center.y;
|
| | Precision devz = closest.z - center.z;
|
| |
|
| | Precision halfwidth = (MaxX - MinX) / 2;
|
| | Precision halfheight = (MaxY - MinY) / 2;
|
| | Precision halfdepth = (MaxZ - MinZ) / 2;
|
| |
|
| |
|
| | if ((fabs(devx) > fabs(devy)) && (fabs(devx) > fabs(devz))) {
|
| | closest.x = center.x + halfwidth * ((devx < 0.0) ? -1.0 : 1.0);
|
| | }
|
| | else if (fabs(devy) > fabs(devz)) {
|
| | closest.y = center.y + halfheight * ((devy < 0.0) ? -1.0 : 1.0);
|
| | }
|
| | else {
|
| | closest.z = center.z + halfdepth * ((devz < 0.0) ? -1.0 : 1.0);
|
| | }
|
| |
|
| |
|
| | closest.x = std::min<Precision>(std::max<Precision>(closest.x, MinX), MaxX);
|
| | closest.y = std::min<Precision>(std::max<Precision>(closest.y, MinY), MaxY);
|
| | closest.z = std::min<Precision>(std::max<Precision>(closest.z, MinZ), MaxZ);
|
| |
|
| | return closest;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox2d BoundBox3<Precision>::ProjectBox(const ViewProjMethod* proj) const
|
| | {
|
| | const int num = 8;
|
| | BoundBox2d clBB2D;
|
| | clBB2D.SetVoid();
|
| |
|
| | for (int i = 0; i < num; i++) {
|
| | Vector3<Precision> clTrsPt = (*proj)(CalcPoint(i));
|
| | clBB2D.Add(Vector2d(clTrsPt.x, clTrsPt.y));
|
| | }
|
| |
|
| | return clBB2D;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline BoundBox3<Precision> BoundBox3<Precision>::Transformed(const Matrix4D& mat) const
|
| | {
|
| | const int num = 8;
|
| | BoundBox3<Precision> bbox;
|
| | for (int i = 0; i < num; i++) {
|
| | bbox.Add(mat * CalcPoint(i));
|
| | }
|
| | return bbox;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Vector3<Precision> BoundBox3<Precision>::GetCenter() const
|
| | {
|
| | return Vector3<Precision>((MaxX + MinX) / 2, (MaxY + MinY) / 2, (MaxZ + MinZ) / 2);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Vector3<Precision> BoundBox3<Precision>::GetMinimum() const
|
| | {
|
| | return Vector3<Precision>(MinX, MinY, MinZ);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Vector3<Precision> BoundBox3<Precision>::GetMaximum() const
|
| | {
|
| | return Vector3<Precision>(MaxX, MaxY, MaxZ);
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Precision BoundBox3<Precision>::CalcDiagonalLength() const
|
| | {
|
| | return static_cast<Precision>(sqrt(
|
| | ((MaxX - MinX) * (MaxX - MinX)) + ((MaxY - MinY) * (MaxY - MinY))
|
| | + ((MaxZ - MinZ) * (MaxZ - MinZ))
|
| | ));
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::SetVoid()
|
| | {
|
| | MinX = MinY = MinZ = std::numeric_limits<Precision>::max();
|
| | MaxX = MaxY = MaxZ = -std::numeric_limits<Precision>::max();
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::Enlarge(Precision fLen)
|
| | {
|
| | MinX -= fLen;
|
| | MinY -= fLen;
|
| | MinZ -= fLen;
|
| | MaxX += fLen;
|
| | MaxY += fLen;
|
| | MaxZ += fLen;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::Shrink(Precision fLen)
|
| | {
|
| | MinX += fLen;
|
| | MinY += fLen;
|
| | MinZ += fLen;
|
| | MaxX -= fLen;
|
| | MaxY -= fLen;
|
| | MaxZ -= fLen;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Precision BoundBox3<Precision>::LengthX() const
|
| | {
|
| | return MaxX - MinX;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Precision BoundBox3<Precision>::LengthY() const
|
| | {
|
| | return MaxY - MinY;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Precision BoundBox3<Precision>::LengthZ() const
|
| | {
|
| | return MaxZ - MinZ;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline Precision BoundBox3<Precision>::Volume() const
|
| | {
|
| | if (!IsValid()) {
|
| | return -1.0;
|
| | }
|
| | return LengthX() * LengthY() * LengthZ();
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::MoveX(Precision value)
|
| | {
|
| | MinX += value;
|
| | MaxX += value;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::MoveY(Precision value)
|
| | {
|
| | MinY += value;
|
| | MaxY += value;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::MoveZ(Precision value)
|
| | {
|
| | MinZ += value;
|
| | MaxZ += value;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::ScaleX(Precision value)
|
| | {
|
| | MinX *= value;
|
| | MaxX *= value;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::ScaleY(Precision value)
|
| | {
|
| | MinY *= value;
|
| | MaxY *= value;
|
| | }
|
| |
|
| | template<class Precision>
|
| | inline void BoundBox3<Precision>::ScaleZ(Precision value)
|
| | {
|
| | MinZ *= value;
|
| | MaxZ *= value;
|
| | }
|
| |
|
| | using BoundBox3f = BoundBox3<float>;
|
| | using BoundBox3d = BoundBox3<double>;
|
| |
|
| | }
|
| |
|
| | #endif
|
| |
|