|
|
|
|
#include "FITKAbsGeoShapeAgent.h"
|
|
|
|
|
#include "FITKVirtualTopoManager.h"
|
|
|
|
|
#include "FITKGeometryMeshVS.h"
|
|
|
|
|
#include "FITKGeometryMeshEntity.h"
|
|
|
|
|
|
|
|
|
|
#include <QVector3D>
|
|
|
|
|
#include <QList>
|
|
|
|
|
#include <QFile>
|
|
|
|
|
#include <QTextStream>
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
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<int, FITKGeoMeshVSFaceEntity*> faceHash = _meshVS->getFaceItems();
|
|
|
|
|
|
|
|
|
|
// 遍历所有面写入STL文件。
|
|
|
|
|
QHashIterator<int, FITKGeoMeshVSFaceEntity*> 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<FITKGeoMeshVSPt*> & facePoints = face->getPoints();
|
|
|
|
|
|
|
|
|
|
// 获取三角面片。
|
|
|
|
|
const QList<FITKGeoMeshVSTri*> & 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<QVector3D> 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<QVector3D> & 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|