LAMPCAE/src/PluginMeshDataExchange/NEUdataExchange.cpp

365 lines
9.8 KiB
C++

#include "NEUdataExchange.h"
#include "MeshData/meshSingleton.h"
#include "MeshData/meshKernal.h"
#include <QFileInfo>
#include <QFile>
#include <QTextStream>
#include <vtkUnstructuredGrid.h>
#include <vtkSmartPointer.h>
#include <vtkDataSet.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkQuad.h>
#include <vtkAppendFilter.h>
#include <vtkTriangle.h>
#include <vtkTetra.h>
#include <vtkDataSet.h>
#include <vtkGAMBITReader.h>
#include <vtkUnsignedCharArray.h>
namespace MeshData
{
NEUdataExchange::NEUdataExchange(const QString &fileName, MeshOperation operation, GUI::MainWindow *mw, int modelId) : MeshThreadBase(fileName, operation, mw),
_fileName(fileName),
_meshData(MeshData::getInstance()),
_operation(operation),
_modelId(modelId)
{
}
NEUdataExchange::~NEUdataExchange()
{
if (_stream)
delete _stream;
}
QString NEUdataExchange::readLine()
{
while (_threadRuning)
{
if (_stream->atEnd())
{
//_threadRuning = false;
return QString();
;
}
QString line = _stream->readLine().simplified();
if (line.isEmpty())
continue;
return line;
}
return QString();
}
bool NEUdataExchange::read()
{
QFileInfo info(_fileName);
if (!info.exists())
return false;
QString name = info.fileName();
QString path = info.filePath();
QFile file(_fileName);
if (!file.open(QIODevice::ReadOnly))
return false;
_stream = new QTextStream(&file);
if (!readBasicInfo())
return false;
vtkSmartPointer<vtkUnstructuredGrid> dataset = vtkSmartPointer<vtkUnstructuredGrid>::New();
// vtkUnstructuredGrid* dataset = vtkUnstructuredGrid::New();
if (!readPoints(dataset))
{
// dataset->Delete();
// dataset = nullptr;
return false;
}
if (!readElements(dataset))
{
// dataset->Delete();
// dataset = nullptr;
return false;
}
file.close();
if (dataset != nullptr)
{
MeshKernal *k = new MeshKernal;
k->setName(name);
k->setPath(path);
k->setMeshData((vtkDataSet *)dataset);
_meshData->appendMeshKernal(k);
return true;
}
return false;
}
bool NEUdataExchange::readBasicInfo()
{
QString line;
while (!_stream->atEnd())
{
if (!_threadRuning)
return false;
line = this->readLine();
if (line.contains("NUMNP") && line.contains("NELEM"))
{
line = this->readLine();
break;
}
}
QStringList info = line.split(" ");
_pointNum = info.at(0).toInt();
_eleNum = info.at(1).toInt();
return true;
}
bool NEUdataExchange::readPoints(vtkUnstructuredGrid *dateset)
{
QString line;
bool ok = false;
while (!_stream->atEnd())
{
if (!_threadRuning)
return false;
line = readLine();
if (line.contains("NODAL COORDINATES"))
break;
}
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
// vtkPoints* points = vtkPoints::New();
for (int i = 0; i < _pointNum; ++i)
{
if (!_threadRuning)
return false;
line = readLine();
double coor[3] = {0};
QStringList scoor = line.split(" ");
if (scoor.size() != 4)
continue;
for (int j = 0; j < 3; ++j)
{
coor[j] = scoor.at(j + 1).toDouble(&ok);
if (!ok)
return false;
}
points->InsertNextPoint(coor);
}
if (points->GetNumberOfPoints() != _pointNum)
{
points->Delete();
return false;
}
dateset->SetPoints(points);
return true;
}
bool NEUdataExchange::readElements(vtkUnstructuredGrid *dateset)
{
QString line;
while (!_stream->atEnd())
{
if (!_threadRuning)
return false;
line = readLine();
if (line.contains("ELEMENTS/CELLS"))
break;
}
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
// type of each cell
vtkUnsignedCharArray *cellTypeList = vtkUnsignedCharArray::New();
cellTypeList->SetNumberOfValues(_eleNum);
unsigned char *cellTypesPtr = cellTypeList->GetPointer(0);
// vtkCellArray* cells = vtkCellArray::New();
for (int i = 0; i < _eleNum; ++i)
{
if (!_threadRuning)
return false;
line = readLine();
QStringList scell = line.split(" ");
// vtkSmartPointer<vtkQuad> cell = vtkSmartPointer<vtkQuad>::New();
// vtkQuad* cell = vtkQuad::New();
// line for element record is:
// NE NTYPE NDP NODE,
// NE: The global element index
// NTYPE: Element type, 1=Edge,2=Quadrilateral,3=Triangle,4=Brick,5=Wedge,6=Tetrahedron,7=Pyramid
// NDP: Number of nodes that define the element
// NODE: List of nodes that define the element
// qDebug() << int(scell[1].toInt());
if (scell[1].toInt() == 2)
{
vtkSmartPointer<vtkQuad> cell = vtkSmartPointer<vtkQuad>::New();
cell->GetPointIds()->SetId(0, scell[3].toInt() - 1);
cell->GetPointIds()->SetId(1, scell[4].toInt() - 1);
cell->GetPointIds()->SetId(2, scell[5].toInt() - 1);
cell->GetPointIds()->SetId(3, scell[6].toInt() - 1);
cells->InsertNextCell(cell);
*cellTypesPtr++ = VTK_QUAD;
}
else if (scell[1].toInt() == 3)
{
vtkSmartPointer<vtkTriangle> cell = vtkSmartPointer<vtkTriangle>::New();
cell->GetPointIds()->SetId(0, scell[3].toInt() - 1);
cell->GetPointIds()->SetId(1, scell[4].toInt() - 1);
cell->GetPointIds()->SetId(2, scell[5].toInt() - 1);
// cell->GetPointIds()->SetId(3, scell[5].toInt()-1);
cells->InsertNextCell(cell);
*cellTypesPtr++ = VTK_TRIANGLE;
}
else if (scell[1].toInt() == 4)
{
vtkSmartPointer<vtkTriangle> cell = vtkSmartPointer<vtkTriangle>::New();
cell->GetPointIds()->SetId(0, scell[3].toInt() - 1);
cell->GetPointIds()->SetId(1, scell[4].toInt() - 1);
cell->GetPointIds()->SetId(2, scell[5].toInt() - 1);
cell->GetPointIds()->SetId(3, scell[6].toInt() - 1);
cell->GetPointIds()->SetId(0, scell[7].toInt() - 1);
cell->GetPointIds()->SetId(1, scell[8].toInt() - 1);
cell->GetPointIds()->SetId(2, scell[9].toInt() - 1);
cell->GetPointIds()->SetId(3, scell[10].toInt() - 1);
cells->InsertNextCell(cell);
*cellTypesPtr++ = VTK_HEXAHEDRON;
}
else if (int(scell[1].toInt()) == 6)
{
vtkSmartPointer<vtkTetra> cell = vtkSmartPointer<vtkTetra>::New();
cell->GetPointIds()->SetId(0, scell[3].toInt() - 1);
cell->GetPointIds()->SetId(1, scell[4].toInt() - 1);
cell->GetPointIds()->SetId(2, scell[5].toInt() - 1);
cell->GetPointIds()->SetId(3, scell[6].toInt() - 1);
cells->InsertNextCell(cell);
*cellTypesPtr++ = VTK_TETRA;
}
else
continue;
// cells->InsertNextCell(cell);
}
if (cells->GetNumberOfCells() != _eleNum)
{
// cells->Delete();
return false;
}
dateset->SetCells(cellTypeList, cells);
return true;
}
bool NEUdataExchange::write()
{
QFile file(_fileName);
if (!file.open(QIODevice::WriteOnly))
return false;
_stream = new QTextStream(&file);
_stream->setCodec("UTF-8");
writeBasicInfo();
// combine dataset
if (_modelId == -1)
{
vtkSmartPointer<vtkAppendFilter> appfilter = vtkSmartPointer<vtkAppendFilter>::New();
int n = _meshData->getKernalCount();
for (int i = 0; i < n; ++i)
{
MeshKernal *k = _meshData->getKernalAt(i);
vtkDataSet *dataset = k->getMeshData();
appfilter->AddInputData(dataset);
}
appfilter->Update();
vtkSmartPointer<vtkUnstructuredGrid> unsGrid = appfilter->GetOutput();
writepoints(unsGrid);
writeElements(unsGrid);
}
else
{
MeshKernal *k = _meshData->getKernalByID(_modelId);
if (k == nullptr)
return false;
vtkDataSet *dataset = k->getMeshData();
writepoints(dataset);
writeElements(dataset);
}
return true;
}
void NEUdataExchange::writeBasicInfo()
{
*_stream << QString(" CONTROL INFO 2.4.6") << endl;
*_stream << QString("** GAMBIT NEUTRAL FILE") << endl;
*_stream << _fileName << endl;
*_stream << QString("PROGRAM: Gambit VERSION: 2.4.6") << endl
<< endl;
}
void NEUdataExchange::writepoints(vtkDataSet *dateset)
{
*_stream << QString(" NUMNP NELEM NGRPS NBSETS NDFCD NDFVL") << endl;
*_stream << QString(" %1 %2 1 0 2 3").arg(dateset->GetNumberOfPoints()).arg(dateset->GetNumberOfCells()) << endl;
*_stream << QString("ENDOFSECTION") << endl;
*_stream << QString(" NODAL COORDINATES 2.4.6") << endl;
const int n = dateset->GetNumberOfPoints();
for (int i = 0; i < n; ++i)
{
if (!_threadRuning)
return;
_stream->setFieldWidth(10);
_stream->setFieldAlignment(QTextStream::AlignRight);
*_stream << i + 1;
double coord[3] = {0.0};
dateset->GetPoint(i, coord);
_stream->setFieldWidth(20);
for (int i = 0; i < 3; ++i)
{
*_stream << QString::number(coord[i], 'g', 11);
}
*_stream << endl;
}
_stream->setFieldWidth(0);
*_stream << QString("ENDOFSECTION") << endl;
}
void NEUdataExchange::writeElements(vtkDataSet *dateset)
{
*_stream << QString(" ELEMENTS/CELLS 2.4.6") << endl;
const int n = dateset->GetNumberOfCells();
for (int i = 0; i < n; ++i)
{
if (!_threadRuning)
return;
_stream->setFieldWidth(8);
*_stream << i + 1;
_stream->setFieldWidth(3);
*_stream << 0;
vtkCell *cell = dateset->GetCell(i);
const int np = cell->GetNumberOfPoints();
*_stream << np << " ";
_stream->setFieldWidth(8);
for (int ip = 0; ip < np; ++ip)
{
int id = cell->GetPointId(ip);
*_stream << id + 1;
}
*_stream << endl;
}
_stream->setFieldWidth(0);
*_stream << QString("ENDOFSECTION");
}
void NEUdataExchange::run()
{
ModuleBase::ThreadTask::run();
bool result = false;
switch (_operation)
{
case MESH_READ:
emit showInformation(tr("Importing NEU Mesh File From \"%1\"").arg(_fileName));
result = read();
setReadResult(result);
break;
case MESH_WRITE:
emit showInformation(tr("Exporting NEU Mesh File To \"%1\"").arg(_fileName));
result = write();
setWriteResult(result);
break;
}
defaultMeshFinished();
}
}