#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 #include #include #include #include #include #include #include #include #include #include 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(); 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(); 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(); 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); } }