#include "FITKAbsGeoShapeAgent.h" #include "FITKVirtualTopoManager.h" #include "FITKGeometryMeshVS.h" #include "FITKGeometryMeshEntity.h" #include #include #include #include #include namespace Interface { FITKAbsGeoShapeAgent::FITKAbsGeoShapeAgent(FITKAbsGeoCommand* command) :_command(command) { _vtmanager = new FITKVirtualTopoManager; _meshVS = new FITKGeometryMeshVS; } FITKAbsGeoShapeAgent::~FITKAbsGeoShapeAgent() { if (_vtmanager) delete _vtmanager; if (_meshVS) delete _meshVS; } void FITKAbsGeoShapeAgent::buildVirtualTopo() { } void FITKAbsGeoShapeAgent::triangulation() { } FITKGeometryMeshVS* FITKAbsGeoShapeAgent::getMeshVS() { return _meshVS; } int FITKAbsGeoShapeAgent::shapeHashCode() { return -1; } FITKGeoEnum::FITKGeoEngine Interface::FITKAbsGeoShapeAgent::getGeoEngine() { //错误值 return FITKGeoEnum::FGENone; } FITKAbsGeoCommand* Interface::FITKAbsGeoShapeAgent::getGeoCommand() { return _command; } FITKVirtualTopoManager* Interface::FITKAbsGeoShapeAgent::getVirtualTopoManager() { return _vtmanager; } bool FITKAbsGeoShapeAgent::writeSTLFile(QString filePath) { if (!_meshVS || !_vtmanager) { return false; } FITKShapeVirtualTopoManager* faceMgr = _vtmanager->getShapeVirtualTopoManager(FITKGeoEnum::VTopoShapeType::VSFace); if (!faceMgr) { return false; } // 写入文件。 QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { return false; } QTextStream stream(&file); // 获取所有面数据。 const QHash faceHash = _meshVS->getFaceItems(); // 遍历所有面写入STL文件。 QHashIterator iter(faceHash); while (iter.hasNext()) { iter.next(); int meshFaceId = iter.key(); FITKAbsVirtualTopo* faceTopo = faceMgr->getDataByID(meshFaceId); if (!faceTopo) { continue; } int faceIndex = faceTopo->getIndexLabel(); FITKGeoMeshVSFaceEntity* face = iter.value(); // 写入面起始标题行。 stream << "solid " << QString("face_%1").arg(faceIndex) << "\n"; // 获取属于面的所有点数据。 const QList & facePoints = face->getPoints(); // 获取三角面片。 const QList & tris = face->getTriangles(); for (FITKGeoMeshVSTri* tri : tris) { // 获取三角面片节点索引。 const int* nodes = tri->getNode(); // 获取三角面片节点。 FITKGeoMeshVSPt* pt1 = facePoints[nodes[0]]; FITKGeoMeshVSPt* pt2 = facePoints[nodes[1]]; FITKGeoMeshVSPt* pt3 = facePoints[nodes[2]]; // 计算三角面片法向。 QList facePointsPos; double nor3[3]{ 0., 0., 0. }; facePointsPos.push_back(QVector3D(pt1->x(), pt1->y(), pt1->z())); facePointsPos.push_back(QVector3D(pt2->x(), pt2->y(), pt2->z())); facePointsPos.push_back(QVector3D(pt3->x(), pt3->y(), pt3->z())); GetFaceNormal(facePointsPos, nor3); // 写入三角面片法向。 stream << " facet normal " << nor3[0] << " " << nor3[1] << " " << nor3[2] << "\n"; // 依次写入面片节点坐标。 stream << " outer loop\n"; stream << " vertex " << pt1->x() << " " << pt1->y() << " " << pt1->z() << "\n"; stream << " vertex " << pt2->x() << " " << pt2->y() << " " << pt2->z() << "\n"; stream << " vertex " << pt3->x() << " " << pt3->y() << " " << pt3->z() << "\n"; stream << " endloop\n"; // 写入三角面片结束标识。 stream << " endfacet\n"; } // 写入分组结束标识。 stream << "endsolid " << QString("face_%1").arg(faceIndex) << "\n"; faceIndex++; } file.close(); return true; } void FITKAbsGeoShapeAgent::GetFaceNormal(QList & points, double* normal) { // 临时数据。 double v[3][3], *v0 = v[0], *v1 = v[1], *v2 = v[2], *tmp; double ax, ay, az, bx, by, bz; // 检查节点数量。 int nPts = points.count(); if (nPts < 3) { return; } // 三角形法向。 if (nPts == 3) { for (int i = 0; i < 3; i++) { v0[i] = points[0][i]; v1[i] = points[1][i]; v2[i] = points[2][i]; } // 根据节点连接顺序获取法向区分正反。 ax = v2[0] - v1[0]; ay = v2[1] - v1[1]; az = v2[2] - v1[2]; bx = v0[0] - v1[0]; by = v0[1] - v1[1]; bz = v0[2] - v1[2]; normal[0] = (ay * bz - az * by); normal[1] = (az * bx - ax * bz); normal[2] = (ax * by - ay * bx); } // 多边形法向。 else { for (int i = 0; i < 3; i++) { v1[i] = points[0][i]; v2[i] = points[1][i]; } for (int i = 0; i < nPts; i++) { tmp = v0; v0 = v1; v1 = v2; v2 = tmp; for (int j = 0; j < 3; j++) { v2[j] = points[(i + 2) % nPts][i]; } // 根据节点连接顺序获取法向区分正反。 ax = v2[0] - v1[0]; ay = v2[1] - v1[1]; az = v2[2] - v1[2]; bx = v0[0] - v1[0]; by = v0[1] - v1[1]; bz = v0[2] - v1[2]; normal[0] += (ay * bz - az * by); normal[1] += (az * bx - ax * bz); normal[2] += (ax * by - ay * bx); } } // 归一化。 double fac = sqrt(pow(normal[0], 2) + pow(normal[1], 2) + pow(normal[2], 2)); if (qFuzzyCompare(fac, 0.)) { return; } for (int i = 0; i < 3; i++) { normal[i] /= fac; } } }