opencascade Bnd_OBB源码学习 OBB包围盒 原创
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;
}
代码说明
-
创建
Bnd_OBB
对象:- 使用中心点 (
gp_Pnt
)、方向向量 (gp_Dir
) 和尺寸 (Standard_Real
) 创建一个Bnd_OBB
对象。 - 使用
SetCenter
、SetXComponent
、SetYComponent
和SetZComponent
方法可以设置Bnd_OBB
对象的属性。
- 使用中心点 (
-
获取
Bnd_OBB
的属性:- 通过
Center()
、XDirection()
、YDirection()
和ZDirection()
获取中心点和方向向量。 - 使用
XHSize()
、YHSize()
和ZHSize()
获取尺寸。 GetVertex
方法用于获取 OBB 的 8 个顶点。
- 通过
-
从 AABB 创建
Bnd_OBB
对象:- 创建一个
Bnd_Box
对象并添加点。 - 从
Bnd_Box
创建Bnd_OBB
对象并获取其属性。
- 创建一个
注意事项
- 确保在构建程序时正确链接 OpenCascade 库。
- 调用
GetVertex
时,检查返回值以确认操作成功。
这个示例涵盖了 Bnd_OBB
类的一些基本用法,包括创建对象、设置属性、获取信息和从 Bnd_Box
创建 Bnd_OBB
。
参考
参考