opencascade Bnd_OBB原始碼學習 OBB包圍盒

一点灯發表於2024-09-20

opencascade Bnd_OBB OBB包圍盒

前言

類描述了定向包圍盒(OBB),比軸對齊包圍盒(AABB)更緊密地包圍形狀的體積。OBB由盒子的中心、軸以及三個維度的一半定義。與AABB相比,OBB在作為非干擾物體的排斥機制時可以更有效地使用。

方法

1. 空建構函式

//! 空建構函式
Bnd_OBB() : myIsAABox(Standard_False)
{
  myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
}

2. 帶有所有定義引數的建構函式

//! 使用所有定義引數的建構函式
Bnd_OBB(const gp_Pnt& theCenter,
        const gp_Dir& theXDirection,
        const gp_Dir& theYDirection,
        const gp_Dir& theZDirection,
        const Standard_Real theHXSize,
        const Standard_Real theHYSize,
        const Standard_Real theHZSize) : myCenter(theCenter.XYZ()),
                                        myIsAABox(Standard_False)
{
  myAxes[0] = theXDirection.XYZ();
  myAxes[1] = theYDirection.XYZ();
  myAxes[2] = theZDirection.XYZ();

  Standard_ASSERT_VOID(theHXSize >= 0.0, "X尺寸的負值");
  Standard_ASSERT_VOID(theHYSize >= 0.0, "Y尺寸的負值");
  Standard_ASSERT_VOID(theHZSize >= 0.0, "Z尺寸的負值");

  myHDims[0] = theHXSize;
  myHDims[1] = theHYSize;
  myHDims[2] = theHZSize;
}

3. 從 AABB 建立 OBB 的建構函式

//! 從 AABB 建立 OBB 的建構函式
Bnd_OBB(const Bnd_Box& theBox) : myIsAABox(Standard_True)
{
  if (theBox.IsVoid())
  {
    myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
    myIsAABox = Standard_False;
    return;
  }

  Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
  theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);

  myAxes[0].SetCoord(1.0, 0.0, 0.0);
  myAxes[1].SetCoord(0.0, 1.0, 0.0);
  myAxes[2].SetCoord(0.0, 0.0, 1.0);

  myHDims[0] = 0.5 * (aX2 - aX1);
  myHDims[1] = 0.5 * (aY2 - aY1);
  myHDims[2] = 0.5 * (aZ2 - aZ1);

  myCenter.SetCoord(0.5 * (aX2 + aX1), 0.5 * (aY2 + aY1), 0.5 * (aZ2 + aZ1));
}

4. 重建 OBB

//! 建立覆蓋所有點的新的 OBB。
//! 每個點的容差由 *theListOfTolerances 陣列設定。
//! 如果陣列不為空,則透過點的容差來擴大結果 Bnd_OBB。
//! <theIsOptimal> 標誌定義了 OBB 的構建模式。
//! 構建最優盒子需要更多時間,但結果通常更緊湊。構建最優 OBB 時,會檢查更多可能的軸。
Standard_EXPORT void ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
                             const TColStd_Array1OfReal *theListOfTolerances = 0,
                             const Standard_Boolean theIsOptimal = Standard_False);

5. 設定 OBB 的中心

設定 OBB 的中心
void SetCenter(const gp_Pnt& theCenter)
{
myCenter = theCenter.XYZ();
}

6. 設定 X 元件

設定 OBB 的 X 元件 - 方向和尺寸
void SetXComponent(const gp_Dir& theXDirection,
const Standard_Real theHXSize)
{
Standard_ASSERT_VOID(theHXSize >= 0.0, "X尺寸的負值");

myAxes[0] = theXDirection.XYZ();
myHDims[0] = theHXSize;
}

7. 設定 Y 元件

//! 設定 OBB 的 Y 元件 - 方向和尺寸
void SetYComponent(const gp_Dir& theYDirection,
const Standard_Real theHYSize)
{
Standard_ASSERT_VOID(theHYSize >= 0.0, "Y尺寸的負值");

myAxes[1] = theYDirection.XYZ();
myHDims[1] = theHYSize;
}

8. 設定 Z 元件

設定 OBB 的 Z 元件 - 方向和尺寸
void SetZComponent(const gp_Dir& theZDirection,
const Standard_Real theHZSize)
{
Standard_ASSERT_VOID(theHZSize >= 0.0, "Z尺寸的負值");

myAxes[2] = theZDirection.XYZ();
myHDims[2] = theHZSize;
}

9. 獲取區域性座標系

返回這個定向盒子的區域性座標系。
將其應用於軸對齊的盒子 ((-XHSize, -YHSize, -ZHSize), (XHSize, YHSize, ZHSize)) 將產生這個定向盒子。
gp_Ax3 Position() const { return gp_Ax3 (myCenter, ZDirection(), XDirection()); }

10. 獲取中心點

返回 OBB 的中心
const gp_XYZ& Center() const
{
return myCenter;
}

11. 獲取 X 方向

返回 OBB 的 X 方向
const gp_XYZ& XDirection() const
{
return myAxes[0];
}

12. 獲取 Y 方向

返回 OBB 的 Y 方向
const gp_XYZ& YDirection() const
{
return myAxes[1];
}

13. 獲取 Z 方向

返回 OBB 的 Z 方向
const gp_XYZ& ZDirection() const
{
return myAxes[2];
}

14. 獲取 X 尺寸

返回 OBB 的 X 尺寸
Standard_Real XHSize() const
{
return myHDims[0];
}

15. 獲取 Y 尺寸

返回 OBB 的 Y 尺寸
Standard_Real YHSize() const
{
return myHDims[1];
}

16. 獲取 Z 尺寸

返回 OBB 的 Z 尺寸
Standard_Real ZHSize() const
{
return myHDims[2];
}

17. 檢查盒子是否為空

檢查盒子是否為空
Standard_Boolean IsVoid() const
{
return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
}

18. 清除盒子

清除這個盒子
void SetVoid()
{
myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
myIsAABox = Standard_False;
}

19. 設定軸對齊盒子標誌

設定軸對齊盒子的標誌
void SetAABox(const Standard_Boolean& theFlag)
{
myIsAABox = theFlag;
}

20. 判斷是否為軸對齊盒子

返回 TRUE 如果盒子是軸對齊的
Standard_Boolean IsAABox() const
{
return myIsAABox;
}

21. 擴大盒子

//! 用給定值擴大盒子
void Enlarge(const Standard_Real theGapAdd)
{
const Standard_Real aGap = Abs(theGapAdd);
myHDims[0] += aGap;
myHDims[1] += aGap;
myHDims[2] += aGap;
}

22. 獲取頂點

返回盒子的頂點陣列。
區域性座標的頂點取決於陣列的索引:
Standard_Boolean GetVertex(gp_Pnt theP[8])

23. 獲取平方對角線長度

返回這個盒子的平方對角線長度
Standard_Real SquareExtent() const
{
return 4.0 * (myHDims[0] * myHDims[0] +
myHDims[1] * myHDims[1] +
myHDims[2] * myHDims[2]);
}

24. 檢查與另一個盒子的干擾

//! 檢查這個盒子是否與另一個盒子不干擾
Standard_EXPORT Standard_Boolean IsOut(const Bnd_OBB& theOther) const;

25. 檢查點是否在此盒子內

//! 檢查點是否在這個盒子內
Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& theP) const;

26. 檢查另一個盒子是否完全在此盒子內

檢查另一個盒子是否完全在這個盒子內
Standard_EXPORT Standard_Boolean IsCompletelyInside(const Bnd_OBB& theOther) const;

27. 將另一個盒子新增到當前盒子中

重建當前盒子以包含所有之前的物件(包括另一個盒子)
Standard_EXPORT void Add(const Bnd_OBB& theOther);

28. 將點新增到當前盒子中

重建當前盒子以包含所有之前的物件(包括一個點)
Standard_EXPORT void Add(const gp_Pnt& theP);


#### 29. 將內容輸出到流中
```cpp
//! 將當前物件的內容輸出到流中
Standard_EXPORT void DumpJson(Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;

下面是一個使用 OpenCascade Bnd_OBB 類的簡單示例。這個示例展示瞭如何建立一個 Bnd_OBB 物件,設定它的屬性,以及如何使用它的一些功能。

示例程式碼

#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
#include <Bnd_OBB.hxx>
#include <Bnd_Box.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_OStream.hxx>
#include <iostream>

int main() {
    // 示例 1: 使用中心點、方向向量和尺寸建立一個 Bnd_OBB 物件
    gp_Pnt center(0.0, 0.0, 0.0);  // 中心點
    gp_Dir xDir(1.0, 0.0, 0.0);    // X 方向
    gp_Dir yDir(0.0, 1.0, 0.0);    // Y 方向
    gp_Dir zDir(0.0, 0.0, 1.0);    // Z 方向
    Standard_Real xSize = 10.0;     // X 尺寸
    Standard_Real ySize = 5.0;      // Y 尺寸
    Standard_Real zSize = 2.0;      // Z 尺寸

    // 建立 Bnd_OBB 物件
    Bnd_OBB obb(center, xDir, yDir, zDir, xSize, ySize, zSize);

    // 輸出 OBB 的中心點和方向
    std::cout << "Center: (" << obb.Center().X() << ", " << obb.Center().Y() << ", " << obb.Center().Z() << ")\n";
    std::cout << "X Direction: (" << obb.XDirection().X() << ", " << obb.XDirection().Y() << ", " << obb.XDirection().Z() << ")\n";
    std::cout << "Y Direction: (" << obb.YDirection().X() << ", " << obb.YDirection().Y() << ", " << obb.YDirection().Z() << ")\n";
    std::cout << "Z Direction: (" << obb.ZDirection().X() << ", " << obb.ZDirection().Y() << ", " << obb.ZDirection().Z() << ")\n";

    // 輸出 OBB 的尺寸
    std::cout << "X Size: " << obb.XHSize() << "\n";
    std::cout << "Y Size: " << obb.YHSize() << "\n";
    std::cout << "Z Size: " << obb.ZHSize() << "\n";

    // 獲取並輸出 OBB 的頂點
    gp_Pnt vertices[8];
    if (obb.GetVertex(vertices)) {
        std::cout << "Vertices:\n";
        for (int i = 0; i < 8; ++i) {
            std::cout << "Vertex " << i << ": (" << vertices[i].X() << ", " << vertices[i].Y() << ", " << vertices[i].Z() << ")\n";
        }
    } else {
        std::cout << "Failed to get vertices.\n";
    }

    // 示例 2: 從 AABB 建立 OBB
    Bnd_Box aabb;
    aabb.Add(gp_Pnt(-5.0, -2.5, -1.0));
    aabb.Add(gp_Pnt(5.0, 2.5, 1.0));

    Bnd_OBB obbFromAABB(aabb);

    // 輸出從 AABB 建立的 OBB 的中心點和尺寸
    std::cout << "Center from AABB: (" << obbFromAABB.Center().X() << ", " << obbFromAABB.Center().Y() << ", " << obbFromAABB.Center().Z() << ")\n";
    std::cout << "X Size from AABB: " << obbFromAABB.XHSize() << "\n";
    std::cout << "Y Size from AABB: " << obbFromAABB.YHSize() << "\n";
    std::cout << "Z Size from AABB: " << obbFromAABB.ZHSize() << "\n";

    return 0;
}

程式碼說明

  1. 建立 Bnd_OBB 物件

    • 使用中心點 (gp_Pnt)、方向向量 (gp_Dir) 和尺寸 (Standard_Real) 建立一個 Bnd_OBB 物件。
    • 使用 SetCenterSetXComponentSetYComponentSetZComponent 方法可以設定 Bnd_OBB 物件的屬性。
  2. 獲取 Bnd_OBB 的屬性

    • 透過 Center()XDirection()YDirection()ZDirection() 獲取中心點和方向向量。
    • 使用 XHSize()YHSize()ZHSize() 獲取尺寸。
    • GetVertex 方法用於獲取 OBB 的 8 個頂點。
  3. 從 AABB 建立 Bnd_OBB 物件

    • 建立一個 Bnd_Box 物件並新增點。
    • Bnd_Box 建立 Bnd_OBB 物件並獲取其屬性。

注意事項

  • 確保在構建程式時正確連結 OpenCascade 庫。
  • 呼叫 GetVertex 時,檢查返回值以確認操作成功。

這個示例涵蓋了 Bnd_OBB 類的一些基本用法,包括建立物件、設定屬性、獲取資訊和從 Bnd_Box 建立 Bnd_OBB
參考
參考

相關文章