You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AppFlow/FITK_Component/FITKGeoCompOCC/FITKOCCShapeTriangulate.cpp

197 lines
7.5 KiB
C++

#include "FITKOCCShapeTriangulate.h"
#include "FITKAbstractOCCModel.h"
#include "FITKOCCVirtualTopoCreator.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsVirtualTopo.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKVirtualTopoManager.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeometryMeshVS.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeometryMeshEntity.h"
#include <TopoDS_Shape.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
#include <QDebug>
#include <QDateTime>
namespace OCC
{
FITKOCCShapeTriangulate::FITKOCCShapeTriangulate(FITKAbstractOCCModel* occModel) : _occModel(occModel)
{
// 初始化
if (occModel == nullptr) return;
// 从模型中获取需要处理的对象
_vtmanager = occModel->getVirtualTopoManager();
_meshVS = occModel->getMeshVS();
}
void FITKOCCShapeTriangulate::triangulate()
{
qDebug() << "tri: " << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
//错误判断
if (_meshVS == nullptr || _vtmanager == nullptr || _occModel == nullptr) return;
// 清除历史三角面片数据。
_meshVS->clear();
// 整体三角面片化。
this->triangulate(*_occModel->getShape());
// 遍历点虚拟拓扑数据
Interface::FITKShapeVirtualTopoManager* sm =
_vtmanager->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VSPoint);
if (sm != nullptr)
for (int i = 0; i < sm->getDataCount(); i++)
{
Interface::FITKAbsVirtualTopo* vtopo = sm->getDataByIndex(i);
if (vtopo == nullptr) continue;
FITKOCCTopoShape* occShape = vtopo->getShapeT<FITKOCCTopoShape>();
if (occShape == nullptr) continue;
const TopoDS_Shape& shape = occShape->getTopoShape();
if (shape.IsNull()) continue;
const int id = vtopo->getDataObjectID();
this->discretePoint(id, shape);
}
// 遍历边虚拟拓扑数据
sm = _vtmanager->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VSEdge);
if (sm != nullptr)
for (int i = 0; i < sm->getDataCount(); i++)
{
Interface::FITKAbsVirtualTopo* vtopo = sm->getDataByIndex(i);
if (vtopo == nullptr) continue;
FITKOCCTopoShape* occShape = vtopo->getShapeT<FITKOCCTopoShape>();
if (occShape == nullptr) continue;
const TopoDS_Shape& shape = occShape->getTopoShape();
if (shape.IsNull()) continue;
const int id = vtopo->getDataObjectID();
this->discreteEdge(id, shape);
}
// 遍历面虚拟拓扑数据
sm = _vtmanager->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VSFace);
if (sm != nullptr)
for (int i = 0; i < sm->getDataCount(); i++)
{
Interface::FITKAbsVirtualTopo* vtopo = sm->getDataByIndex(i);
if (vtopo == nullptr) continue;
FITKOCCTopoShape* occShape = vtopo->getShapeT<FITKOCCTopoShape>();
if (occShape == nullptr) continue;
const TopoDS_Shape& shape = occShape->getTopoShape();
if (shape.IsNull()) continue;
const int id = vtopo->getDataObjectID();
this->discreteFace(id, shape);
}
qDebug() << "tri finished: " << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
}
void FITKOCCShapeTriangulate::discretePoint(const int id, const TopoDS_Shape& shape)
{
//记录点坐标
TopoDS_Vertex vertex = TopoDS::Vertex(shape);
gp_Pnt pt = BRep_Tool::Pnt(vertex);
Interface::FITKGeoMeshVSPt * vpt = new Interface::FITKGeoMeshVSPt();
vpt->setXYZ(pt.X(), pt.Y(), pt.Z());
_meshVS->insertPoint(id, vpt);
}
void FITKOCCShapeTriangulate::discreteEdge(const int id, const TopoDS_Shape& shape)
{
//三角化边
this->triangulate(shape,0.0005);
TopLoc_Location loc;
const TopoDS_Edge & edge = TopoDS::Edge(shape);
//获取离散点
const Handle(Poly_Polygon3D) & mesh = BRep_Tool::Polygon3D(edge, loc);
if (!mesh) return;
const int nPts = mesh->NbNodes();
const TColgp_Array1OfPnt & nodes = mesh->Nodes();
gp_Trsf trans(loc);
Interface::FITKGeoMeshVSEdgeEntity* vsedge = new Interface::FITKGeoMeshVSEdgeEntity;
for (Standard_Integer i = 1; i <= nPts; i++)
{
//记录点坐标
gp_Pnt pt = nodes.Value(i);
pt.Transform(trans);
Interface::FITKGeoMeshVSPt * vpt = new Interface::FITKGeoMeshVSPt();
vpt->setXYZ(pt.X(), pt.Y(), pt.Z());
vsedge->appendPoint(vpt);
}
//记录边
_meshVS->insertEdge(id, vsedge);
}
void FITKOCCShapeTriangulate::discreteFace(const int id, const TopoDS_Shape& shape)
{
//三角化面
// this->triangulate(shape);
//获取面
TopLoc_Location loc;
const TopoDS_Face & face = TopoDS::Face(shape);
const Handle(Poly_Triangulation) & mesh = BRep_Tool::Triangulation(face, loc);
if (!mesh) return;
int nPts = mesh->NbNodes();
int nCells = mesh->NbTriangles();
const TColgp_Array1OfPnt & nodes = mesh->Nodes();
const Poly_Array1OfTriangle & triangles = mesh->Triangles();
gp_Trsf trans(loc);
//记录点坐标
Interface::FITKGeoMeshVSFaceEntity* vsface = new Interface::FITKGeoMeshVSFaceEntity;
for (Standard_Integer i = 1; i <= nPts; i++)
{
gp_Pnt pt = nodes.Value(i);
pt.Transform(trans);
Interface::FITKGeoMeshVSPt * vpt = new Interface::FITKGeoMeshVSPt();
vpt->setXYZ(pt.X(), pt.Y(), pt.Z());
vsface->appendPoint(vpt);
}
//记录三角形
for (Standard_Integer i = 1; i <= nCells; i++)
{
Poly_Triangle tri = triangles.Value(i);
int pt1{ -1 }, pt2{ -1 }, pt3{-1};
tri.Get(pt1, pt2, pt3);
//判断方向
if (face.Orientation() == TopAbs_REVERSED)
{
Interface::FITKGeoMeshVSTri * vsTri = new Interface::FITKGeoMeshVSTri(pt3 - 1, pt2 - 1, pt1 - 1);
vsface->appendMeshTri(vsTri);
}
else
{
Interface::FITKGeoMeshVSTri * vsTri = new Interface::FITKGeoMeshVSTri(pt1 - 1, pt2 - 1, pt3 - 1);
vsface->appendMeshTri(vsTri);
}
}
//记录面对象
_meshVS->insertFace(id, vsface);
}
void FITKOCCShapeTriangulate::triangulate(const TopoDS_Shape & shape, double factor)
{
// 获取包围盒尺寸。
Bnd_Box box;
BRepBndLib::Add(shape, box);
double xMin, xMax, yMin, yMax, zMin, zMax;
box.Get(xMin, yMin, zMin, xMax, yMax, zMax);
double sizeFactor = sqrt(pow(xMax - xMin, 2) + pow(yMax - yMin, 2) + pow(zMax - zMin, 2));
double lineDef = factor * sizeFactor;
// 划分参数。
IMeshTools_Parameters params;
params.Deflection = lineDef;
// 网格划分。(三角面片化)
BRepMesh_IncrementalMesh(shape, params);
}
}