在UG8.5环境下,进行 NX二次开发,通过OBB算法获取实体的最小包容盒,C++语言实现
时间: 2023-12-10 15:39:42 浏览: 163
使用opencv部署yolov5-obb遥感数据检测的C++实现源码.zip
在 UG8.5 环境下,获取实体的最小包容盒需要使用 OBB 算法,其中 OBB 算法是一种针对三维物体的最小包围盒计算方法,其基本思想是先将物体沿着各个轴进行投影,再通过计算投影矩形的中心、半径和方向,确定物体的最小包围盒。
下面是一个使用 C++ 实现 OBB 算法获取实体最小包容盒的示例代码:
```cpp
#include <NXOpen/NXException.hxx>
#include <NXOpen/Body.hxx>
#include <NXOpen/DisplayableObject.hxx>
#include <NXOpen/Matrix3x3.hxx>
#include <NXOpen/Point3d.hxx>
#include <NXOpen/Unit.hxx>
#include <NXOpen/UnitCollection.hxx>
#include <NXOpen/Vector3d.hxx>
#include <vector>
using namespace std;
using namespace NXOpen;
class OBB
{
public:
Point3d center;
Vector3d axis[3];
double halfSize[3];
};
class OBBBuilder
{
public:
OBB BuildOBB(Body* body);
private:
void GetBoundingBox(Body* body, Point3d& minPoint, Point3d& maxPoint);
void ComputeOBB(vector<Point3d>& points, OBB& obb);
void ComputeCovarianceMatrix(vector<Point3d>& points, Matrix3x3& covariance);
void ComputeEigenVectors(Matrix3x3& covariance, Vector3d eigenVectors[3]);
void ComputeHalfSize(vector<Point3d>& points, OBB& obb);
};
OBB OBBBuilder::BuildOBB(Body* body)
{
OBB obb;
Point3d minPoint;
Point3d maxPoint;
GetBoundingBox(body, minPoint, maxPoint);
vector<Point3d> points;
points.push_back(minPoint);
points.push_back(Point3d(maxPoint.X, minPoint.Y, minPoint.Z));
points.push_back(Point3d(maxPoint.X, maxPoint.Y, minPoint.Z));
points.push_back(Point3d(minPoint.X, maxPoint.Y, minPoint.Z));
points.push_back(Point3d(minPoint.X, minPoint.Y, maxPoint.Z));
points.push_back(Point3d(maxPoint.X, minPoint.Y, maxPoint.Z));
points.push_back(Point3d(maxPoint.X, maxPoint.Y, maxPoint.Z));
points.push_back(Point3d(minPoint.X, maxPoint.Y, maxPoint.Z));
ComputeOBB(points, obb);
return obb;
}
void OBBBuilder::GetBoundingBox(Body* body, Point3d& minPoint, Point3d& maxPoint)
{
DisplayableObject* displayableObject = body;
if (displayableObject == NULL)
throw NXException::Create("Failed to get displayable object from body");
Tag tag = displayableObject->GetTag();
if (tag == NULL_TAG)
throw NXException::Create("Failed to get tag from displayable object");
double min[3];
double max[3];
UF_MODL_ask_body_bbox(tag, min, max);
minPoint.X = min[0];
minPoint.Y = min[1];
minPoint.Z = min[2];
maxPoint.X = max[0];
maxPoint.Y = max[1];
maxPoint.Z = max[2];
}
void OBBBuilder::ComputeOBB(vector<Point3d>& points, OBB& obb)
{
Matrix3x3 covariance;
ComputeCovarianceMatrix(points, covariance);
Vector3d eigenVectors[3];
ComputeEigenVectors(covariance, eigenVectors);
obb.center.X = 0.0;
obb.center.Y = 0.0;
obb.center.Z = 0.0;
for (int i = 0; i < 3; i++)
{
obb.axis[i] = eigenVectors[i];
double maxExtent = -1e300;
double minExtent = 1e300;
for (int j = 0; j < 8; j++)
{
Point3d point = points[j];
double extent = point.Dot(eigenVectors[i]);
if (extent > maxExtent)
maxExtent = extent;
if (extent < minExtent)
minExtent = extent;
}
obb.center += eigenVectors[i] * ((maxExtent + minExtent) * 0.5);
obb.halfSize[i] = (maxExtent - minExtent) * 0.5;
}
}
void OBBBuilder::ComputeCovarianceMatrix(vector<Point3d>& points, Matrix3x3& covariance)
{
int count = points.size();
double sum[9] = { 0.0 };
double centroid[3] = { 0.0 };
for (int i = 0; i < count; i++)
{
Point3d point = points[i];
centroid[0] += point.X;
centroid[1] += point.Y;
centroid[2] += point.Z;
sum[0] += point.X * point.X;
sum[1] += point.X * point.Y;
sum[2] += point.X * point.Z;
sum[3] += point.Y * point.Y;
sum[4] += point.Y * point.Z;
sum[5] += point.Z * point.Z;
}
centroid[0] /= count;
centroid[1] /= count;
centroid[2] /= count;
sum[0] -= centroid[0] * centroid[0] * count;
sum[1] -= centroid[0] * centroid[1] * count;
sum[2] -= centroid[0] * centroid[2] * count;
sum[3] -= centroid[1] * centroid[1] * count;
sum[4] -= centroid[1] * centroid[2] * count;
sum[5] -= centroid[2] * centroid[2] * count;
covariance.SetValues(sum);
}
void OBBBuilder::ComputeEigenVectors(Matrix3x3& covariance, Vector3d eigenVectors[3])
{
double eigenValues[3];
covariance.ComputeEigenValuesAndVectors(eigenValues, eigenVectors);
}
void OBBBuilder::ComputeHalfSize(vector<Point3d>& points, OBB& obb)
{
for (int i = 0; i < 3; i++)
{
double maxExtent = -1e300;
double minExtent = 1e300;
for (int j = 0; j < 8; j++)
{
Point3d point = points[j];
double extent = point.Dot(obb.axis[i]);
if (extent > maxExtent)
maxExtent = extent;
if (extent < minExtent)
minExtent = extent;
}
obb.halfSize[i] = (maxExtent - minExtent) * 0.5;
}
}
```
在上述代码中,OBBBuilder 类提供了一个 BuildOBB 方法,该方法接受一个 Body 对象作为参数,并返回一个 OBB 对象,该对象包含了实体的最小包容盒信息。在 BuildOBB 方法中,首先通过 GetBoundingBox 方法获取实体的边界框信息,然后根据边界框信息计算出实体的八个顶点坐标,并将这些坐标存储在 points 向量中。接下来,通过 ComputeOBB 方法计算实体的最小包容盒信息,该方法会先计算出实体的协方差矩阵,然后通过计算该矩阵的特征向量,求出实体的三个主轴和中心点。最后,通过 ComputeHalfSize 方法计算实体的半边长信息,并将这些信息存储在 OBB 对象中返回。
阅读全文