49#ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
51#ifdef ENABLE_POLYHEDRALMESH_SUPPORT
57void remove_duplicated_vertices(std::vector<quint32>& _indices)
59 std::vector<quint32>::iterator endIter = _indices.end();
60 for (std::vector<quint32>::iterator iter = _indices.begin(); iter != endIter; ++iter)
61 endIter = std::remove(iter+1, endIter, *(iter));
63 _indices.erase(endIter,_indices.end());
70 forceTriangleMesh_(false),
71 forcePolyMesh_(false),
75 saveVertexNormals_(0),
76 saveVertexTexCoords_(0),
77 savePrecisionLabel_(0),
89 if(OpenFlipperSettings().value(
"FileVtk/Save/Binary",
false).toBool())
90 userWriteOptions_ |= BINARY;
91 if(OpenFlipperSettings().value(
"FileVtk/Save/FaceNormals",
true).toBool())
92 userWriteOptions_ |= FACENORMALS;
93 if(OpenFlipperSettings().value(
"FileVtk/Save/VertexNormals",
true).toBool())
94 userWriteOptions_ |= VERTEXNORMALS;
95 if(OpenFlipperSettings().value(
"FileVtk/Save/VertexTexCoords",
true).toBool())
96 userWriteOptions_ |= VERTEXTEXCOORDS;
102 return QString( tr(
"Visualization Toolkit ASCII ( *.vtk )") );
108 return QString( tr(
"Visualization Toolkit ASCII ( *.vtk )") );
116#ifdef ENABLE_POLYHEDRALMESH_SUPPORT
119#ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
122#ifdef ENABLE_TETRAHEDRALMESH_SUPPORT
139 if (saveOptions_ == 0){
141 saveOptions_ =
new QWidget();
142 QVBoxLayout* layout =
new QVBoxLayout();
143 layout->setAlignment(Qt::AlignTop);
145 saveBinary_ =
new QCheckBox(
"Save Binary");
146 layout->addWidget(saveBinary_);
147 saveBinary_->setCheckable(
false);
149 saveFaceNormals_ =
new QCheckBox(
"Save Face Normals");
150 layout->addWidget(saveFaceNormals_);
152 saveVertexNormals_ =
new QCheckBox(
"Save Vertex Normals");
153 layout->addWidget(saveVertexNormals_);
155 saveVertexTexCoords_ =
new QCheckBox(
"Save Vertex TexCoords");
156 layout->addWidget(saveVertexTexCoords_);
158 savePrecisionLabel_ =
new QLabel(
"Writer Precision");
159 layout->addWidget(savePrecisionLabel_);
161 savePrecision_ =
new QSpinBox();
162 savePrecision_->setMinimum(1);
163 savePrecision_->setMaximum(12);
164 savePrecision_->setValue(6);
165 layout->addWidget(savePrecision_);
167 saveDefaultButton_ =
new QPushButton(
"Make Default");
168 layout->addWidget(saveDefaultButton_);
170 saveOptions_->setLayout(layout);
172 connect(saveBinary_, SIGNAL(clicked(
bool)), savePrecision_, SLOT(setDisabled(
bool)));
173 connect(saveDefaultButton_, SIGNAL(clicked()),
this, SLOT(
slotSaveDefault()));
175 saveBinary_->setChecked( OpenFlipperSettings().value(
"FileVtk/Save/Binary",
false).toBool() );
176 saveFaceNormals_->setChecked( OpenFlipperSettings().value(
"FileVtk/Save/FaceNormals",
true).toBool() );
177 saveVertexNormals_->setChecked( OpenFlipperSettings().value(
"FileVtk/Save/VertexNormals",
true).toBool() );
178 saveVertexTexCoords_->setChecked( OpenFlipperSettings().value(
"FileVtk/Save/VertexTexCoords",
true).toBool() );
187 OpenFlipperSettings().
setValue(
"FileVtk/Save/Binary", saveBinary_->isChecked() );
188 OpenFlipperSettings().
setValue(
"FileVtk/Save/FaceNormals", saveFaceNormals_->isChecked() );
189 OpenFlipperSettings().
setValue(
"FileVtk/Save/VertexNormals", saveVertexNormals_->isChecked() );
190 OpenFlipperSettings().
setValue(
"FileVtk/Save/VertexTexCoords", saveVertexTexCoords_->isChecked() );
203template <
typename MeshT>
206 emit log(
LOGWARN,tr(
"Unsupported Cell Type TETRA") );
210template <
typename MeshT>
213 emit log(
LOGWARN,tr(
"Unsupported Cell Type HEXAHEDRON") );
217template <
typename MeshT>
220 emit log(
LOGWARN,tr(
"Unsupported Cell Type WEDGE") );
224template <
typename MeshT>
227 emit log(
LOGWARN,tr(
"Unsupported Cell Type PYRAMID") );
231template <
typename MeshT>
234 std::vector<OpenMesh::VertexHandle> handles;
235 for (std::vector<quint32>::const_iterator it = _indices.begin(); it != _indices.end(); ++it)
236 handles.push_back(_mesh->vertex_handle(*it));
243 std::vector< OpenMesh::VertexHandle > inverseHandles;
244 for (
int i = handles.size()-1 ; i >= 0 ; --i)
245 inverseHandles.push_back(handles[i]);
247 fh = _mesh->
add_face(inverseHandles);
256template <
typename MeshT>
262 return _mesh->
add_face(v1,v2,v3).idx();
265template <
typename MeshT>
268 _mesh->update_face_normals();
275template <
typename MeshT>
278 _mesh->update_vertex_normals();
281template <
typename MeshT>
286 if (! _mesh->get_property_handle(originalVertexIdx,
"FileVTKPlugin_originalVertexIdx")) {
287 _mesh->remove_property( originalVertexIdx );
291template <
typename MeshT>
296 _mesh->set_normal( vh , _normal );
300template <
typename MeshT>
305 _mesh->set_normal( fh, _normal );
308template <
typename MeshT>
311 if ((_cell.type <= 4) || (_cell.type >= 10))
314 emit log(
LOGWARN,tr(
"Normals not supported for type %1").arg(_cell.type) );
316 else if (_cell.type == 5)
321 else if (_cell.type == 6)
324 int numberOfTriangles = _cell.indices.size() - 2;
326 for (
int i = 0; i < numberOfTriangles; i++)
329 else if ((_cell.type >= 7) && (_cell.type <= 9))
332 if (forceTriangleMesh_)
338 int numberOfTriangles = _cell.indices.size() - 2;
339 for (
int i = 0; i < numberOfTriangles; i++)
351template <
typename MeshT>
356 if (! _mesh->get_property_handle(originalVertexIdx,
"FileVTKPlugin_originalVertexIdx")) {
363 for(
auto vit : _mesh->vertices()) {
364 if ( _mesh->property(originalVertexIdx, vit).
is_valid() ) {
366 _mesh->set_normal( vit, _mesh->
normal(_mesh->property (originalVertexIdx, vit) ) );
371template<
class MeshT >
374 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0)
375 _out.precision(savePrecision_->value());
377 _out <<
"DATASET POLYDATA\n";
379 typename MeshT::Point p;
380 typename MeshT::Normal n;
382 typename MeshT::TexCoord2D t;
384 int total_face_vertices = _mesh.
n_faces();
385 for (
auto fit : _mesh.faces()) {
386 total_face_vertices += _mesh.
valence(fit);
389 _out <<
"POINTS " << _mesh.
n_vertices() <<
" float\n";
390 for (
auto vit : _mesh.vertices()) {
392 p = _mesh.point(vit);
393 _out << p[0] <<
" " << p[1] <<
" " << p[2];
398 _out <<
"POLYGONS "<< _mesh.
n_faces() <<
" " << total_face_vertices <<
"\n";
399 for (
auto fit : _mesh.faces()) {
401 _out << fit.valence();
404 for (
auto fvit : fit.vertices()) {
405 _out <<
" " << fvit.idx();
415 _out <<
"CELL_DATA "<< _mesh.
n_faces() <<
"\n";
418 if (_mesh.has_face_normals() && (userWriteOptions_ & FileVTKPlugin::FACENORMALS)) {
419 _out <<
"NORMALS faceNormals float\n";
420 for (
auto fit : _mesh.faces()) {
422 _out << n[0] <<
" " << n[1] <<
" " << n[2];
428 _out <<
"POINT_DATA "<< _mesh.
n_vertices() <<
"\n";
431 if (_mesh.has_vertex_normals() && (userWriteOptions_ & FileVTKPlugin::VERTEXNORMALS)) {
432 _out <<
"NORMALS vertexNormals float\n";
433 for (
auto vit : _mesh.vertices()) {
435 _out << n[0] <<
" " << n[1] <<
" " << n[2];
441 if (_mesh.has_vertex_texcoords2D() && (userWriteOptions_ & FileVTKPlugin::VERTEXTEXCOORDS)) {
442 _out <<
"TEXTURE_COORDINATES vertexTexcoords 2 float\n";
443 for (
auto vit : _mesh.vertices()) {
444 t = _mesh.texcoord2D(vit);
445 _out << t[0] <<
" " << t[1];
490#if defined(ENABLE_HEXAHEDRALMESH_SUPPORT) || defined(ENABLE_POLYHEDRALMESH_SUPPORT) || defined(ENABLE_TETRAHEDRALMESH_SUPPORT)
492template <
typename MeshT>
493int FileVTKPlugin::addTetraCellToOpenVolumeMesh(
MeshT _mesh, std::vector<quint32> _indices)
495 if (_indices.size() != 4)
498 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
499 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
503 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
507 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
511 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
516 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
517 for (
unsigned int i = 0; i < faces.size(); i++)
518 halffacehandles.push_back(_mesh->
halfface(faces[i]));
520 for (
unsigned int i = 0; i < halffacehandles.size(); i++)
528 return _mesh->
add_cell(halffacehandles).idx();
532template <
typename MeshT>
533int FileVTKPlugin::addHexaCellToOpenVolumeMesh(
MeshT _mesh, std::vector<quint32> _indices)
535 if (_indices.size() != 8)
536 { emit log(
LOGWARN,tr(
"Expected 8 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
538 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
539 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
544 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
549 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
554 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
559 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
564 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
570 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
571 for (
unsigned int i = 0; i < faces.size(); i++)
572 halffacehandles.push_back(_mesh->
halfface(faces[i]));
574 for (
unsigned int i = 0; i < halffacehandles.size(); i++)
582 return _mesh->
add_cell(halffacehandles).idx();
585template <
typename MeshT>
586int FileVTKPlugin::addWedgeCellToOpenVolumeMesh(
MeshT _mesh, std::vector<quint32> _indices)
588 if (_indices.size() != 6)
589 { emit log(
LOGWARN,tr(
"Expected 6 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
591 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
592 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
597 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
601 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
605 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
610 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
616 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
617 for (
unsigned int i = 0; i < faces.size(); i++)
618 halffacehandles.push_back(_mesh->
halfface(faces[i]));
620 for (
unsigned int i = 0; i < halffacehandles.size(); i++)
628 return _mesh->
add_cell(halffacehandles).idx();
631template <
typename MeshT>
632int FileVTKPlugin::addPyramidCellToOpenVolumeMesh(
MeshT _mesh, std::vector<quint32> _indices)
634 if (_indices.size() != 6)
635 { emit log(
LOGWARN,tr(
"Expected 6 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
637 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
638 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
643 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
647 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
651 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
655 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
660 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
661 for (
unsigned int i = 0; i < faces.size(); i++)
662 halffacehandles.push_back(_mesh->
halfface(faces[i]));
664 for (
unsigned int i = 0; i < halffacehandles.size(); i++)
672 return _mesh->
add_cell(halffacehandles).idx();
675template <
typename MeshT>
676int FileVTKPlugin::addFaceToOpenVolumeMesh(
MeshT*& _mesh, std::vector<quint32> _indices)
678 if (_indices.size() < 3)
679 { emit log(
LOGWARN,tr(
"Expected at least 3 indices to add a face but got %1").arg(_indices.size()) ); }
681 std::vector<OpenVolumeMesh::VertexHandle> face;
682 for (
unsigned int i = 0; i < _indices.size(); i++)
687 halffacehandle = _mesh->
halfface(face);
688 if (!halffacehandle.is_valid())
693 return halffacehandle.idx();
696template <
typename MeshT>
697int FileVTKPlugin::addFaceToOpenVolumeMesh(
MeshT*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3)
699 std::vector<OpenVolumeMesh::VertexHandle> face;
705 halffacehandle = _mesh->
halfface(face);
706 if (!halffacehandle.is_valid())
711 return halffacehandle.idx();
714template <
typename MeshT>
715void FileVTKPlugin::addVertexNormalToOpenVolumeMesh(
MeshT _mesh, quint32 _index,
OpenMesh::Vec3d _normal)
721template <
typename MeshT>
722void FileVTKPlugin::addFaceNormalToOpenVolumeMesh(
MeshT _mesh, quint32 _index,
OpenMesh::Vec3d _normal)
729 faceNormals[fh] = _normal;
731 faceNormals[fh] = -_normal;
735template <
typename MeshT>
738 int incidentFaces = _mesh.
cell(_cellHandle).halffaces().size();
739 int incidentVertices = 0;
743 if ((incidentFaces == 4) && (incidentVertices == 4))
745 else if ((incidentFaces == 6) && (incidentVertices == 8))
747 else if ((incidentFaces == 5) && (incidentVertices == 6))
749 else if ((incidentFaces == 5) && (incidentVertices == 5))
755template <
typename MeshT>
758 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.
face(_faceHandle).halfedges();
759 if (halfedges.size() == 3)
765template <
typename MeshT>
774 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = face.halfedges();
775 std::vector<int> indices;
776 for (
unsigned int i = 0; i < halfedges.size(); i++)
777 indices.push_back(_mesh.
halfedge(halfedges[i]).from_vertex().idx());
779 if ((cvit->idx() != indices[0]) && ((*cvit).idx() != indices[1]) && ((*cvit).idx() != indices[2]))
780 indices.push_back(cvit->idx());
783 else if (_cellType == 12)
790 std::vector<int> indices;
791 for (
unsigned int i = 0; i < 4; i++)
794 indices.push_back(edge.from_vertex().idx());
800 heh = _mesh.opposite_halfedge_handle(heh);
804 heh = _mesh.opposite_halfedge_handle(heh);
807 for (
unsigned int i = 0; i < 4; i++)
810 indices.push_back(edge.to_vertex().idx());
815 else if (_cellType == 13)
820 for (
unsigned int i = 0; i < cell.halffaces().size(); i++)
821 if (_mesh.
halfface(cell.halffaces()[i]).halfedges().size() == 3)
822 hfh = cell.halffaces()[i];
825 std::vector<int> indices;
826 for (
unsigned int i = 0; i < 3; i++)
829 indices.push_back(edge.from_vertex().idx());
835 heh = _mesh.opposite_halfedge_handle(heh);
839 heh = _mesh.opposite_halfedge_handle(heh);
842 for (
unsigned int i = 0; i < 3; i++)
845 indices.push_back(edge.to_vertex().idx());
851 else if (_cellType == 14)
856 std::vector<OpenVolumeMesh::HalfFaceHandle> halffaces = cell.halffaces();
858 for (
unsigned int i = 0; i < halffaces.size(); i++)
859 if (_mesh.
halfface(halffaces[i]).halfedges().size() == 4)
860 face = _mesh.
halfface(halffaces[i]);
861 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = face.halfedges();
862 std::vector<int> indices;
863 for (
unsigned int i = 0; i < halfedges.size(); i++)
864 indices.push_back(_mesh.
halfedge(halfedges[i]).from_vertex().idx());
866 if ((cvit->idx() != indices[0]) && ((*cvit).idx() != indices[1]) && ((*cvit).idx() != indices[2]) && ((*cvit).idx() != indices[3]))
867 indices.push_back(cvit->idx());
871 return std::vector<int>();
874template <
typename MeshT>
875bool FileVTKPlugin::writeASCIIDataOfOpenVolumeMesh(std::ostream& _out,
MeshT& _mesh)
877 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0)
878 _out.precision(savePrecision_->value());
880 _out <<
"DATASET UNSTRUCTURED_GRID\n";
885 _out <<
"POINTS " << _mesh.
n_vertices() <<
" float\n";
886 for (
auto vit : _mesh.vertices()) {
889 _out << p[0] <<
" " << p[1] <<
" " << p[2];
905 quint32 listSize = 0;
906 for (
auto cit : _mesh.cells())
908 int cellType = getCellType(_mesh, cit);
912 else if (cellType == 12 )
914 else if (cellType == 13 )
916 else if (cellType == 14 )
923 std::vector<OpenVolumeMesh::HalfFaceHandle> halffaces = _mesh.
cell(cit).halffaces();
924 for (
unsigned int i = 0; i < halffaces.size(); i++)
927 if (!(fpAlreadyStored[fh]))
931 if (!(userWriteOptions_ & FileVTKPlugin::FACENORMALS))
932 fpAlreadyStored[fh] =
true;
935 for (std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator heit = face.halfedges().begin();
936 heit != face.halfedges().end();
947 if (!(fpAlreadyStored[*fit]))
950 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.
face(*fit).halfedges();
951 for (
unsigned int i = 0; i < halfedges.size(); i++)
952 epAlreadyStored[_mesh.
edge_handle(halfedges[i])] =
true;
955 listSize += 1 + halfedges.size();
961 for (
auto eit : _mesh.edges())
963 if (!(epAlreadyStored[eit]))
970 _out <<
"CELLS " << cellCount <<
" " << listSize <<
"\n";
975 for (
auto cit : _mesh.cells())
979 int cellType = getCellType(_mesh, cit);
984 else if (cellType == 12 )
986 else if (cellType == 13 )
988 else if (cellType == 14 )
997 std::vector<int> indices = getCellVertexIndices(_mesh, cit, cellType);
998 _out << indices.size();
999 for (
unsigned int i = 0; i < indices.size(); i++)
1000 _out <<
" " << indices[i];
1008 for (
auto fit : _mesh.faces())
1010 if (!(fpAlreadyStored[fit]))
1012 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.
face(fit).halfedges();
1014 _out << halfedges.size();
1015 for (
unsigned int i = 0; i < halfedges.size(); i++)
1019 _out <<
" " << edge.from_vertex().idx();
1029 for (
auto eit : _mesh.edges())
1031 if (!(epAlreadyStored[eit]))
1035 _out <<
" " << edge.from_vertex().idx();
1036 _out <<
" " << edge.to_vertex().idx();
1045 _out <<
"CELL_TYPES " << cellCount <<
"\n";
1048 for (
auto cit : _mesh.cells())
1050 int cellType = getCellType(_mesh, cit);
1054 _out << cellType <<
"\n";
1059 for (
auto fit : _mesh.faces())
1061 if (!(fpAlreadyStored[fit]))
1063 int cellType = getCellType(_mesh,fit);
1067 _out << cellType <<
"\n";
1073 for (
auto eit : _mesh.edges())
1075 if (!(epAlreadyStored[eit]))
1092 if ((userWriteOptions_ & FileVTKPlugin::VERTEXNORMALS))
1094 _out <<
"POINT_DATA "<< _mesh.
n_vertices() <<
"\n";
1097 _out <<
"NORMALS vertex_normals float\n";
1098 for (
auto v_it : _mesh.vertices()) {
1100 _out << n[0] <<
" " << n[1] <<
" " << n[2];
1107 if ((userWriteOptions_ & FileVTKPlugin::FACENORMALS))
1109 _out <<
"CELL_DATA "<< cellCount <<
"\n";
1110 _out <<
"NORMALS face_normals float\n";
1113 for (
auto cit : _mesh.cells())
1115 int cellType = getCellType(_mesh, cit);
1117 if (cellType == -1 )
1121 _out << 1 <<
" " << 0 <<
" " << 0;
1130 for (
auto fit : _mesh.faces()) {
1132 _out << n[0] <<
" " << n[1] <<
" " << n[2];
1138 for (
auto eit : _mesh.edges())
1140 if (!(epAlreadyStored[eit]))
1142 _out << 1 <<
" " << 0 <<
" " << 0;
1155#ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
1168#ifdef ENABLE_POLYHEDRALMESH_SUPPORT
1181#ifdef ENABLE_TETRAHEDRALMESH_SUPPORT
1201 QFile file(_filename);
1203 if ( !file.open(QIODevice::ReadOnly) ) {
1207 QTextStream in(&file);
1209 QString line = in.readLine();
1212#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1213 QStringList header = line.split(
" ",QString::SkipEmptyParts);
1215 QStringList header = line.split(
" ",Qt::SkipEmptyParts);
1218 if ( header.size() != 5 ) {
1222 QString version = header[4];
1224 header.removeLast();
1226 QString magic = header.join(
" ");
1228 if ( magic !=
"# vtk DataFile Version" ) {
1234 QString fileTypeStr = in.readLine();
1236 fileTypeStr = fileTypeStr.simplified();
1238 if ( fileTypeStr.toLower() ==
"binary" ) {
1240 }
else if ( fileTypeStr.toLower() ==
"ascii" ) {
1248 while ( line.simplified() ==
"" )
1249 line = in.readLine();
1251#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1252 QStringList datasetList = line.split(
" ",QString::SkipEmptyParts);
1254 QStringList datasetList = line.split(
" ",Qt::SkipEmptyParts);
1259 if ( datasetList.size() != 2 ) {
1265 datasetList[1] = datasetList[1].simplified();
1267 if ( datasetList[1] ==
"STRUCTURED_POINTS" )
1268 dataset = STRUCTURED_POINTS;
1269 else if ( datasetList[1] ==
"STRUCTURED_GRID" )
1270 dataset = STRUCTURED_GRID;
1271 else if ( datasetList[1] ==
"RECTILINEAR_GRID" )
1272 dataset = RECTILINEAR_GRID;
1273 else if ( datasetList[1] ==
"POLYDATA" )
1275 else if ( datasetList[1] ==
"UNSTRUCTURED_GRID" )
1276 dataset = UNSTRUCTURED_GRID;
1282 if ((dataset == STRUCTURED_POINTS) || (dataset == STRUCTURED_GRID) || (dataset == RECTILINEAR_GRID) )
1287 else if (dataset == POLYDATA)
1294 line = in.readLine();
1297 while ( !line.contains(
"POLYGONS") ) {
1305 line = in.readLine();
1308#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1309 QStringList polygonsLine = line.split(
" ",QString::SkipEmptyParts);
1311 QStringList polygonsLine = line.split(
" ",Qt::SkipEmptyParts);
1316 if ( polygonsLine.size() != 3 ) {
1317 emit log(
LOGERR,tr(
"Expected to get Points line with exactly 3 entries, but %1 found!").arg(polygonsLine.size()));
1324 quint32 polygoncount = polygonsLine[1].toUInt(&ok);
1327 emit log(
LOGERR,tr(
"Expected to get number of points and entries, but read %1 !").arg(polygonsLine.join(
" ")));
1332 while ( read < polygoncount) {
1339 in.device()->read((
char*)&valence,
sizeof(quint32));
1344 return BMT_PolyMesh;
1350 for (
unsigned int i = 0 ; i < valence; ++i ) {
1356 in.device()->read((
char*)&valence,
sizeof(quint32));
1372 line = in.readLine();
1375 while ( !line.contains(
"CELL_TYPES") ) {
1383 line = in.readLine();
1387#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1388 QStringList cellLine = line.split(
" ",QString::SkipEmptyParts);
1390 QStringList cellLine = line.split(
" ",Qt::SkipEmptyParts);
1395 if ( cellLine.size() != 2 ) {
1396 emit log(
LOGERR,tr(
"Expected to get CELL_TYPES line with exactly 2 entries, but %1 found!").arg(cellLine.size()));
1403 quint32 cellCountTypes = cellLine[1].toUInt(&ok);
1406 emit log(
LOGERR,tr(
"Expected to get number of cell types, but read %1 !").arg(cellLine[1]));
1410 bool triMeshPossible =
true;
1411 bool polyMeshPossible =
true;
1413#ifndef ENABLE_HEXAHEDRALMESH_SUPPORT
1414 bool hexahedralMeshPossible =
false;
1416 bool hexahedralMeshPossible =
true;
1418#ifndef ENABLE_POLYHEDRALMESH_SUPPORT
1419 bool polyhedralMeshPossible =
false;
1421 bool polyhedralMeshPossible =
true;
1423#ifndef ENABLE_TETRAHEDRALMESH_SUPPORT
1424 bool tetrahedralMeshPossible =
false;
1426 bool tetrahedralMeshPossible =
true;
1430 while ( read < cellCountTypes) {
1437 in.device()->read((
char*)&type,
sizeof(quint32));
1440 if (( 1 <= type ) && (type <= 6 ))
1444 hexahedralMeshPossible =
false;
1445 tetrahedralMeshPossible =
false;
1447 else if (( 7 <= type ) && (type <= 9 ))
1452 triMeshPossible =
false;
1453 hexahedralMeshPossible =
false;
1454 tetrahedralMeshPossible =
false;
1457 else if ( 10 == type )
1460 triMeshPossible =
false;
1461 polyMeshPossible =
false;
1462 hexahedralMeshPossible =
false;
1464 else if (( 13 == type ) || (type == 14 ))
1468 triMeshPossible =
false;
1469 polyMeshPossible =
false;
1470 hexahedralMeshPossible =
false;
1471 tetrahedralMeshPossible =
false;
1474 else if (( 11 == type ) || ( 12 == type ))
1478 triMeshPossible =
false;
1479 polyMeshPossible =
false;
1483 if ( in.status() != QTextStream::Ok ) {
1484 emit log(
LOGERR,tr(
"Read corrupted cell type data!"));
1490 if (triMeshPossible)
1492 else if (polyMeshPossible)
1493 return BMT_PolyMesh;
1494 else if (hexahedralMeshPossible)
1495 return BMT_HexahedralMesh;
1496 else if (tetrahedralMeshPossible)
1497 return BMT_TetrahedralMesh;
1498 else if (polyhedralMeshPossible)
1499 return BMT_PolyhedralMesh;
1510 std::cerr <<
"Loading vtk file" << std::endl;
1514 QFile file(_filename);
1516 if ( !file.open(QIODevice::ReadOnly) ) {
1517 emit log(
LOGERR,
"Unable to open vtk file!");
1521 QTextStream in(&file);
1523 std::cerr <<
"File is open!" << std::endl;
1525 QString line = in.readLine();
1527 std::cerr <<
"Got line: " << std::endl;
1528 std::cerr << line.toStdString() << std::endl;
1529#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1530 QStringList header = line.split(
" ",QString::SkipEmptyParts);
1532 QStringList header = line.split(
" ",Qt::SkipEmptyParts);
1536 if ( header.size() != 5 ) {
1537 emit log(
LOGERR,tr(
"Bad VTK header? ") + line);
1541 QString version = header[4];
1543 header.removeLast();
1545 QString magic = header.join(
" ");
1547 if ( magic !=
"# vtk DataFile Version" ) {
1548 emit log(
LOGERR,tr(
"Bad VTK header magic? ") + magic);
1554 QString fileTypeStr = in.readLine();
1556 fileTypeStr = fileTypeStr.simplified();
1558 if ( fileTypeStr.toLower() ==
"binary" ) {
1560 emit log(
LOGINFO,tr(
"Loading VTK binary file of version %1.").arg(version));
1561 emit log(
LOGERR,tr(
"Not yet implemented!"));
1562 }
else if ( fileTypeStr.toLower() ==
"ascii" ) {
1564 emit log(
LOGINFO,tr(
"Loading VTK ascii file of version %1.").arg(version));
1566 emit log(
LOGERR,tr(
"Bad VTK type? ") + fileTypeStr);
1574 while ( line.simplified() ==
"" )
1575 line = in.readLine();
1577#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1578 QStringList datasetList = line.split(
" ",QString::SkipEmptyParts);
1580 QStringList datasetList = line.split(
" ",Qt::SkipEmptyParts);
1582 if ( datasetList.size() != 2 ) {
1583 emit log(
LOGERR,tr(
"Bad dataset specification!"));
1589 datasetList[1] = datasetList[1].simplified();
1591 if ( datasetList[1] ==
"STRUCTURED_POINTS" )
1592 dataset = STRUCTURED_POINTS;
1593 else if ( datasetList[1] ==
"STRUCTURED_GRID" )
1594 dataset = STRUCTURED_GRID;
1595 else if ( datasetList[1] ==
"RECTILINEAR_GRID" )
1596 dataset = RECTILINEAR_GRID;
1597 else if ( datasetList[1] ==
"POLYDATA" )
1599 else if ( datasetList[1] ==
"UNSTRUCTURED_GRID" )
1600 dataset = UNSTRUCTURED_GRID;
1602 emit log(
LOGERR,tr(
"Unknown dataset specification! %1").arg(datasetList[1]));
1607 bool is_OpenVolumeMesh =
false;
1609 if ( (forceTriangleMesh_) || (bestType == BMT_TriMesh) ){
1623 if ( !loadMesh(in,_mesh,dataset) ) {
1624 emit log(
LOGERR,
"Unable to load mesh!");
1628 emit log(
LOGERR,
"Unable to add empty triangle mesh!");
1638 else if ((bestType == BMT_PolyMesh) || (bestType == BMT_None))
1653 if ( !loadMesh(in,_mesh,dataset) ) {
1654 emit log(
LOGERR,
"Unable to load mesh!");
1658 emit log(
LOGERR,
"Unable to add empty poly mesh!");
1668#ifdef ENABLE_POLYHEDRALMESH_SUPPORT
1669 else if (bestType == BMT_PolyhedralMesh)
1672 is_OpenVolumeMesh =
true;
1684 if ( !loadMesh(in,_mesh,dataset) ) {
1685 emit log(
LOGERR,
"Unable to load mesh!");
1689 emit log(
LOGERR,
"Unable to add empty polyhedral mesh!");
1698#ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
1699 else if (bestType == BMT_HexahedralMesh)
1702 is_OpenVolumeMesh =
true;
1714 if ( !loadMesh(in,_mesh,dataset) ) {
1715 emit log(
LOGERR,
"Unable to load mesh!");
1719 emit log(
LOGERR,
"Unable to add empty hexahedral mesh!");
1727#ifdef ENABLE_TETRAHEDRALMESH_SUPPORT
1728 else if (bestType == BMT_TetrahedralMesh)
1731 is_OpenVolumeMesh =
true;
1743 if ( !loadMesh(in,_mesh,dataset) ) {
1744 emit log(
LOGERR,
"Unable to load mesh!");
1748 emit log(
LOGERR,
"Unable to add empty tetrahedral mesh!");
1762 if (is_OpenVolumeMesh)
1771 emit openedFile( baseObj->
id() );
1773 return baseObj->
id();
1776 emit log(
LOGERR,tr(
"Error in load mesh!"));
1783template <
typename MeshT>
1786 std::cerr <<
"loadMeshPoints" << std::endl;
1791#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1792 QStringList pointsLine = _spec.split(
" ",QString::SkipEmptyParts);
1794 QStringList pointsLine = _spec.split(
" ",Qt::SkipEmptyParts);
1799 if ( pointsLine.size() != 3 ) {
1800 emit log(
LOGERR,tr(
"Expected to get Points line with exactly 3 entries, but %1 found!").arg(pointsLine.size()));
1805 quint32 points = pointsLine[1].toUInt(&ok);
1808 emit log(
LOGERR,tr(
"Expected to get number of points, but read %1 !").arg(pointsLine[1]));
1816 while ( read < points ) {
1822 if ( pointsLine[2] ==
"float" ) {
1825 _in.device()->read((
char*)&vecf[0],
sizeof(
float));
1826 _in.device()->read((
char*)&vecf[1],
sizeof(
float));
1827 _in.device()->read((
char*)&vecf[2],
sizeof(
float));
1832 emit log(
LOGERR,tr(
"Not implemented data type %1 !").arg(pointsLine[2]));
1838 _in >> vec[0] >> vec[1] >> vec[2];
1845 if ( _in.status() == QTextStream::Ok ) {
1848 emit log(
LOGERR,tr(
"Read corrupted point data!"));
1855 if ( pointsLine[2] ==
"float" ) {
1858 _in.seek(_in.pos() + read * 3 *
sizeof(
float) /
sizeof(
char) );
1866template <
typename MeshT>
1868 std::cerr <<
"loadMeshLines" << std::endl;
1873#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1874 QStringList linesLine = _spec.split(
" ",QString::SkipEmptyParts);
1876 QStringList linesLine = _spec.split(
" ",Qt::SkipEmptyParts);
1881 if ( linesLine.size() != 3 ) {
1882 emit log(
LOGERR,tr(
"Expected to get LINES line with exactly 3 entries, but %1 found!").arg(linesLine.size()));
1887 quint32 linecount = linesLine[1].toUInt(&ok);
1890 quint32 entrycount = linesLine[2].toUInt(&ok);
1893 emit log(
LOGERR,tr(
"Expected to get number of lines and entries, but read %1 !").arg(linesLine.join(
" ")));
1899 while ( read < linecount) {
1907 _in.device()->read((
char*)&valence,
sizeof(quint32));
1912 if ( _in.status() == QTextStream::Ok ) {
1915 for (
unsigned int i = 0 ; i < valence; ++i )
1918 for (
unsigned int i = 0 ; i < valence; ++i )
1919 _in.device()->read((
char*)&valence,
sizeof(quint32));
1922 if ( _in.status() == QTextStream::Ok ) {
1927 emit log(
LOGERR,tr(
"Read corrupted face data!"));
1932 emit log(
LOGERR,tr(
"Read corrupted POLYGONS data!"));
1942 _in.seek(_in.pos() + entrycount *
sizeof(quint32) /
sizeof(
char) );
1945 emit log(
LOGWARN,tr(
"Lines not supported yet ... skipped!"));
1950template <
typename MeshT>
1952 std::cerr <<
"loadMeshPolygons" << std::endl;
1957#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1958 QStringList polygonsLine = _spec.split(
" ",QString::SkipEmptyParts);
1960 QStringList polygonsLine = _spec.split(
" ",Qt::SkipEmptyParts);
1965 if ( polygonsLine.size() != 3 ) {
1966 emit log(
LOGERR,tr(
"Expected to get Points line with exactly 3 entries, but %1 found!").arg(polygonsLine.size()));
1971 quint32 polygoncount = polygonsLine[1].toUInt(&ok);
1974 quint32 entrycount = polygonsLine[2].toUInt(&ok);
1977 emit log(
LOGERR,tr(
"Expected to get number of points and entries, but read %1 !").arg(polygonsLine.join(
" ")));
1982 bool errorEnabled = omerr().is_enabled();
1986 while ( read < polygoncount) {
1993 _in.device()->read((
char*)&valence,
sizeof(quint32));
1997 std::vector< quint32 > indices;
1999 for (
unsigned int i = 0 ; i < valence; ++i ) {
2005 _in.device()->read((
char*)&valence,
sizeof(quint32));
2008 indices.push_back( index );
2011 if ( _in.status() == QTextStream::Ok ) {
2014 remove_duplicated_vertices(indices);
2016 if (indices.size() >= 3)
2020 cell.indices = indices;
2021 cell.index =
addFace(_mesh, indices);
2022 _cells.push_back(cell);
2025 emit log(
LOGERR,tr(
"Read corrupted face data!"));
2043 _in.seek(_in.pos() + entrycount *
sizeof(qint32) /
sizeof(
char) );
2049template <
typename MeshT>
2054 if (_vhandles.empty())
return -1;
2057 if (! _mesh->get_property_handle(originalVertexIdx,
"FileVTKPlugin_originalVertexIdx")) {
2058 _mesh->add_property( originalVertexIdx,
"FileVTKPlugin_originalVertexIdx" );
2061 for(
auto vit : _mesh->vertices()) {
2067 for (
unsigned int j = 0; j < _vhandles.size(); ++j)
2069 typename MeshT::Point p = _mesh->point(_vhandles[j]);
2076 if (_mesh->has_vertex_status()) {
2077 _mesh->status(_vhandles[j]).set_fixed_nonmanifold(
true);
2080 _mesh->property (originalVertexIdx, _vhandles[j]) = original_handle;
2087 if (_mesh->has_face_status())
2088 _mesh->status(fh).set_fixed_nonmanifold(
true);
2091 if (_mesh->has_edge_status()) {
2092 for (
auto fe_it : fh.
edges()) {
2093 _mesh->status(fe_it).set_fixed_nonmanifold(
true);
2101template <
typename MeshT>
2103 std::cerr <<
"loadMeshTriangleStrips" << std::endl;
2108#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2109 QStringList triStripsLine = _spec.split(
" ",QString::SkipEmptyParts);
2111 QStringList triStripsLine = _spec.split(
" ",Qt::SkipEmptyParts);
2116 if ( triStripsLine.size() != 3 ) {
2117 emit log(
LOGERR,tr(
"Expected to get TRIANGLE_STRIPS line with exactly 3 entries, but %1 found!").arg(triStripsLine.size()));
2122 quint32 stripcount = triStripsLine[1].toUInt(&ok);
2125 quint32 entrycount = triStripsLine[2].toUInt(&ok);
2128 emit log(
LOGERR,tr(
"Expected to get number of strips and entries, but read %1 !").arg(triStripsLine.join(
" ")));
2133 while ( read < stripcount) {
2140 _in.device()->read((
char*)&valence,
sizeof(quint32));
2144 QList< quint32 > indices;
2147 for (
unsigned int i = 0 ; i < 2; ++i ) {
2153 _in.device()->read((
char*)&valence,
sizeof(quint32));
2156 indices.push_back( index );
2160 for (
unsigned int i = 2 ; i < valence; ++i ) {
2166 _in.device()->read((
char*)&valence,
sizeof(quint32));
2169 indices.push_back( index );
2171 if ( _in.status() == QTextStream::Ok ) {
2175 cell.indices.resize(3);
2176 cell.indices[0] = indices[i];
2177 cell.indices[1] = indices[i-1];
2178 cell.indices[2] = indices[i-2];
2180 std::swap(cell.indices[1],cell.indices[2]);
2181 cell.index =
addFace(_mesh, cell.indices);
2182 _cells.push_back(cell);
2184 emit log(
LOGERR,tr(
"Read corrupted face data!"));
2198 _in.seek(_in.pos() + entrycount *
sizeof(qint32) /
sizeof(
char) );
2204template <
typename MeshT>
2206 std::cerr <<
"loadMeshNormals" << std::endl;
2209#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2210 QStringList normalsLine = _spec.split(
" ",QString::SkipEmptyParts);
2212 QStringList normalsLine = _spec.split(
" ",Qt::SkipEmptyParts);
2218 if ( normalsLine.size() != 3 ) {
2219 emit log(
LOGERR,tr(
"Expected to get NORMALS line with exactly 3 entries, but %1 found!").arg(normalsLine.size()));
2227 while ( read < _count) {
2232 if ( normalsLine[2] ==
"float" ) {
2236 _in.device()->read((
char*)&vecf[0],
sizeof(
float));
2237 _in.device()->read((
char*)&vecf[1],
sizeof(
float));
2238 _in.device()->read((
char*)&vecf[2],
sizeof(
float));
2243 emit log(
LOGERR,tr(
"Not implemented data type %1 !").arg(normalsLine[2]));
2249 _in >> normal[0] >> normal[1] >> normal[2];
2253 if ( _in.status() == QTextStream::Ok ) {
2255 if ( _pointNormal ) {
2263 emit log(
LOGERR,tr(
"Read corrupted point data!"));
2272 if ( normalsLine[2] ==
"float" ) {
2275 _in.seek(_in.pos() + read * 3 *
sizeof(
float) /
sizeof(
char) );
2285template <
typename MeshT>
2288 std::cerr <<
"loadMeshCells" << std::endl;
2291#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2292 QStringList cellLine = _spec.split(
" ",QString::SkipEmptyParts);
2294 QStringList cellLine = _spec.split(
" ",Qt::SkipEmptyParts);
2299 if ( cellLine.size() != 3 ) {
2300 emit log(
LOGERR,tr(
"Expected to get CELLS line with exactly 3 entries, but %1 found!").arg(cellLine.size()));
2307 quint32 cellCount = cellLine[1].toUInt(&ok);
2310 quint32 entryCount = cellLine[2].toUInt(&ok);
2314 emit log(
LOGERR,tr(
"Expected to get number of cells and entries, but read %1 !").arg(cellLine.join(
" ")));
2319 while ( read < cellCount) {
2328 _in.device()->read((
char*)&valence,
sizeof(quint32));
2333 for (
unsigned int i = 0 ; i < valence; ++i ) {
2339 _in.device()->read((
char*)&valence,
sizeof(quint32));
2342 currentCell.indices.push_back( index );
2345 if ( _in.status() == QTextStream::Ok ) {
2346 _cells.push_back(currentCell);
2348 emit log(
LOGERR,tr(
"Read corrupted face data!"));
2358 _in.seek(_in.pos() + entryCount *
sizeof(quint32) /
sizeof(
char) );
2370 while ( _spec.simplified().size() == 0 ) {
2373 if ( _in.atEnd() ) {
2374 emit log(
LOGERR,tr(
"File end when reading cell specification!"));
2378 _spec = _in.readLine();
2381 if ( ! _spec.contains(
"CELL_TYPES") ) {
2382 emit log(
LOGERR,tr(
"Wrong token! Expected CELL_TYPES but got : %1").arg(_spec));
2387#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2388 cellLine = _spec.split(
" ",QString::SkipEmptyParts);
2390 cellLine = _spec.split(
" ",Qt::SkipEmptyParts);
2395 if ( cellLine.size() != 2 ) {
2396 emit log(
LOGERR,tr(
"Expected to get CELL_TYPES line with exactly 2 entries, but %1 found!").arg(cellLine.size()));
2401 quint32 cellCountTypes = cellLine[1].toUInt(&ok);
2404 emit log(
LOGERR,tr(
"Expected to get number of cell types, but read %1 !").arg(cellLine[1]));
2408 if (cellCountTypes != cellCount ) {
2409 emit log(
LOGERR,tr(
"cellCountTypes != cellCount !").arg(cellLine.size()));
2414 while ( read < cellCount) {
2421 _in.device()->read((
char*)&type,
sizeof(quint32));
2425 _cells[read].type = type;
2427 if ( _in.status() != QTextStream::Ok ) {
2428 emit log(
LOGERR,tr(
"Read corrupted cell type data!"));
2437 _in.seek(_in.pos() + read *
sizeof(quint32) /
sizeof(
char) );
2445 for (
unsigned int i = 0 ; i < _cells.size() ; ++i ) {
2446 if ( _cells[i].type == 1 ) {
2451 }
else if ( _cells[i].type == 2 ) {
2456 }
else if ( _cells[i].type == 3 ) {
2459 emit log(
LOGWARN,tr(
"Unsupported Cell Type LINE") );
2461 }
else if ( _cells[i].type == 4 ) {
2464 emit log(
LOGWARN,tr(
"Unsupported Cell Type POLY_LINE") );
2466 }
else if ( _cells[i].type == 5 ) {
2468 _cells[i].index =
addFace(_mesh, _cells[i].indices);
2469 }
else if ( _cells[i].type == 6 ) {
2472 for (
unsigned int j = 2 ; j < _cells[i].indices.size() ; ++j) {
2474 _cells[i].index =
addFace(_mesh, _cells[i].indices[j-2],_cells[i].indices[j],_cells[i].indices[j-1]);
2476 _cells[i].index =
addFace(_mesh, _cells[i].indices[j-2],_cells[i].indices[j-1],_cells[i].indices[j]);
2481 }
else if ( _cells[i].type == 7 ) {
2484 _cells[i].index =
addFace(_mesh, _cells[i].indices);
2486 }
else if ( _cells[i].type == 8 ) {
2489 emit log(
LOGWARN,tr(
"Unsupported Cell Type PIXEL") );
2491 }
else if ( _cells[i].type == 9 ) {
2494 _cells[i].index =
addFace(_mesh, _cells[i].indices);
2496 }
else if ( _cells[i].type == 10 ) {
2498 _cells[i].index =
addTetraCell(_mesh, _cells[i].indices);
2500 }
else if ( _cells[i].type == 11 ) {
2503 emit log(
LOGWARN,tr(
"Unsupported Cell Type VOXEL") );
2505 }
else if ( _cells[i].type == 12 ) {
2508 _cells[i].index =
addHexaCell(_mesh, _cells[i].indices);
2509 }
else if ( _cells[i].type == 13 ) {
2512 _cells[i].index =
addWedgeCell(_mesh, _cells[i].indices);
2513 }
else if ( _cells[i].type == 14 ) {
2519 emit log(
LOGERR,tr(
"Unknown cell type").arg(_cells[i].type) );
2523 std::cerr <<
"Read " << read <<
" Cells " << std::endl;
2524 std::cerr <<
"Vector has size: " << _cells.size() << std::endl;
2530template <
typename MeshT>
2531bool FileVTKPlugin::loadMesh(QTextStream& _in,
MeshT*& _mesh, Dataset _type){
2534 if ( _type != POLYDATA && _type != UNSTRUCTURED_GRID ) {
2535 emit log(
LOGERR,
"Unsupported DATASET" );
2544 bool pointNormalsRead =
false;
2545 bool faceNormalsRead =
false;
2548 bool pointData =
false;
2551 quint32 pointDataSize = 0;
2554 bool cellData =
false;
2557 quint32 cellDataSize = 0;
2559 std::vector<CellType> cells;
2563 line = _in.readLine();
2566 while ( line.simplified().size() == 0 ) {
2569 if ( _in.atEnd() ) {
2571 std::cerr <<
"atEnd" << std::endl;
2575 line = _in.readLine();
2582 std::cerr <<
"Line is: " << line.toStdString() << std::endl;
2585 if ( line.contains(
"POINTS") ) {
2588 }
else if ( line.contains(
"POINT_DATA") ) {
2591#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2592 QStringList pointDataLine = line.split(
" ",QString::SkipEmptyParts);
2594 QStringList pointDataLine = line.split(
" ",Qt::SkipEmptyParts);
2599 if ( pointDataLine.size() != 2 ) {
2600 emit log(
LOGERR,tr(
"Expected to get POINT_DATA line with exactly 2 entries, but %1 found!").arg(line.size()));
2605 pointDataSize = pointDataLine[1].toUInt(&ok);
2610 std::cerr <<
"Point data mode with " << pointDataSize <<
"Elements" << std::endl;
2612 }
else if ( line.contains(
"CELL_DATA") ) {
2615#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2616 QStringList cellDataLine = line.split(
" ",QString::SkipEmptyParts);
2618 QStringList cellDataLine = line.split(
" ",Qt::SkipEmptyParts);
2622 if ( cellDataLine.size() != 2 ) {
2623 emit log(
LOGERR,tr(
"Expected to get CELL_DATA line with exactly 2 entries, but %1 found!").arg(line.size()));
2628 cellDataSize = cellDataLine[1].toUInt(&ok);
2633 std::cerr <<
"Cell data mode with " << cellDataSize <<
"Elements" << std::endl;
2635 }
else if ( line.contains(
"VERTICES") ) {
2636 std::cerr <<
"Vertices will be skipped as they are already added!" << std::endl;
2637 }
else if ( line.contains(
"LINES") ) {
2639 }
else if ( line.contains(
"POLYGONS") ) {
2641 }
else if ( line.contains(
"TRIANGLE_STRIPS") ) {
2643 }
else if ( line.contains(
"CELL") ) {
2645 }
else if ( line.contains(
"NORMALS") ) {
2649 pointNormalsRead =
true;
2650 }
else if (cellData) {
2652 faceNormalsRead =
true;
2654 emit log(
LOGERR,tr(
"Got normals keyword but we are neither in pointdata nor celldata mode") );
2659 std::cerr <<
"Unrecognized keyword : " << line.toStdString() << std::endl;
2664 if ( !faceNormalsRead )
2667 if ( !pointNormalsRead )
2681 forceTriangleMesh_ =
true;
2683 forcePolyMesh_ =
true;
2690bool FileVTKPlugin::saveObject(
int _id, QString _filename) {
2694 emit log(
LOGERR, tr(
"saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
2698 std::string filename = std::string( _filename.toUtf8() );
2700 std::fstream ofs( filename.c_str(), std::ios_base::out );
2704 emit log(
LOGERR, tr(
"saveObject : Cannot not open file %1 for writing!").arg(_filename) );
2713 object->setFromFileName(_filename);
2714 object->setName(object->
filename());
2719 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2723 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2729 object->setFromFileName(_filename);
2730 object->setName(object->
filename());
2735 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2739 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2744#ifdef ENABLE_POLYHEDRALMESH_SUPPORT
2748 object->setFromFileName(_filename);
2749 object->setName(object->
filename());
2754 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2758 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2764#ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
2768 object->setFromFileName(_filename);
2769 object->setName(object->
filename());
2774 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2778 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2784#ifdef ENABLE_TETRAHEDRALMESH_SUPPORT
2788 object->setFromFileName(_filename);
2789 object->setName(object->
filename());
2794 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
2798 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
2806 emit log(
LOGERR, tr(
"Unable to save (object is not a compatible mesh type)"));
2815template<
class MeshT >
2822 _out <<
"# vtk DataFile Version 2.0\n";
2824 _out <<
"Mesh saved from OpenFlipper - www.openflipper.org\n";
2844 if( OpenFlipper::Options::nogui() )
2849 if(saveBinary_->isChecked()) userWriteOptions_ |= BINARY;
2850 else {
if(userWriteOptions_ & BINARY) userWriteOptions_ -= BINARY; }
2852 if(saveFaceNormals_) {
2853 if(saveFaceNormals_->isChecked()) userWriteOptions_ |= FACENORMALS;
2854 else {
if(userWriteOptions_ & FACENORMALS) userWriteOptions_ -= FACENORMALS; }
2856 if(saveVertexNormals_) {
2857 if(saveVertexNormals_->isChecked()) userWriteOptions_ |= VERTEXNORMALS;
2858 else {
if(userWriteOptions_ & VERTEXNORMALS) userWriteOptions_ -= VERTEXNORMALS; }
2860 if(saveVertexTexCoords_) {
2861 if(saveVertexTexCoords_->isChecked()) userWriteOptions_ |= VERTEXTEXCOORDS;
2862 else {
if(userWriteOptions_ & VERTEXTEXCOORDS) userWriteOptions_ -= VERTEXTEXCOORDS; }
const DataType DATA_GROUP(1)
Items used for Grouping.
#define DATA_HEXAHEDRAL_MESH
#define DATA_POLYHEDRAL_MESH
#define DATA_TETRAHEDRAL_MESH
#define DATA_TRIANGLE_MESH
virtual void setName(QString _name) override
path to the file from which the object is loaded ( defaults to "." )
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
QString filename() const
return the filename of the object
bool dataType(DataType _type) const
void setFromFileName(const QString &_filename)
void setNormalsOfDuplicatedVerticesOfOpenMesh(MeshT *&_mesh)
Sets normals of duplicated vertices that were created for non-manifold meshes.
FileVTKPlugin()
Constructor.
void removeTemporaryProperties(TriMesh *&_mesh)
Removed temporary properties that might have been added during file reading.
void addFaceNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a face normal.
bool writeASCIIDataOfOpenMesh(std::ostream &_out, MeshT &_mesh)
Writes the data of the VTK file in ASCII format.
void slotSaveDefault()
Slot called when user wants to save the given Save options as default.
void removeTemporaryPropertiesOfOpenMesh(MeshT *&_mesh)
Removed temporary properties that might have been added during file reading.
int loadObject(QString _filename)
Loads Object and converts it to a triangle mesh if possible.
QString description()
Return a description of what the plugin is doing.
void updateVertexNormals(TriMesh *&_mesh)
Updates vertex normals.
BestMeshType findBestObjectType(QString _filename)
Reads the file to check for present primitives and returns the object type that fits best.
bool loadMeshLines(QString _spec, QTextStream &_in, MeshT *&_mesh)
Reads lines from the stream and adds them to the mesh.
void addVertexNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a vertex normal.
int addWedgeCell(TriMesh *&_mesh, const std::vector< quint32 > &_indices)
Adds a wedge cell to the mesh. (Does nothing, yet)
void updateVertexNormalsOfOpenMesh(MeshT *&_mesh)
Updates vertex normals.
void updateFaceNormals(TriMesh *&_mesh)
Updates face normals.
bool loadMeshTriangleStrips(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads triangle strips from the stream and adds them to the mesh.
void addFaceNormal(TriMesh *&_mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a face normal.
bool writeMesh(std::ostream &_out, MeshT &_mesh)
Writes the header of the VTK file, then calls writeASCIIData (binary VTK is currently unsupported)
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
int addHexaCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a hexa cell to the mesh. (Does nothing, yet)
int addPyramidCell(TriMesh *&_mesh, const std::vector< quint32 > &_indices)
Adds a pyramid cell to the mesh. (Does nothing, yet)
int addPyramidCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a pyramid cell to the mesh. (Does nothing, yet)
void addCellNormal(MeshT *&_mesh, const CellType &_cell, OpenMesh::Vec3d _normal)
Adds a normal to the cell.
int addTetraCell(TriMesh *&_mesh, const std::vector< quint32 > &_indices)
Adds a tetra cell to the mesh. (Does nothing, yet)
bool binary_
Reading binary file?
int add_non_manifold_face(MeshT *&_mesh, std::vector< OpenMesh::VertexHandle > &_vhandles)
Helper function for loadMeshPolygons() that takes care of adding non-manifold faces.
int addTetraCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a tetra cell to the mesh. (Does nothing, yet)
QWidget * loadOptionsWidget(QString)
void setNormalsOfDuplicatedVertices(TriMesh *&_mesh)
Sets normals of duplicated vertices that were created for non-manifold meshes.
QWidget * saveOptionsWidget(QString)
bool loadMeshPoints(QString _spec, QTextStream &_in, MeshT *&_mesh)
Reads points from the stream and adds them to the mesh.
int addWedgeCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a wedge cell to the mesh. (Does nothing, yet)
int addHexaCell(TriMesh *&_mesh, const std::vector< quint32 > &_indices)
Adds a hexa cell to the mesh. (Does nothing, yet)
int addFace(TriMesh *&_mesh, const std::vector< quint32 > &_indices)
Adds a face to the mesh.
bool loadMeshNormals(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells, bool _pointNormal, quint32 _count)
Reads Normals from the stream and adds them to the mesh.
void initializePlugin()
Initialize Plugin.
int addFaceToOpenMesh(MeshT *&_mesh, std::vector< quint32 > _indices)
Adds a face to the mesh.
bool loadMeshCells(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads unstructured grid data from the stream and adds it to the mesh.
bool writeASCIIData(std::ostream &_out, TriMesh &_mesh)
Writes the data of the VTK file in ASCII format.
bool loadMeshPolygons(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads polygons from the stream and adds them to the mesh.
void addVertexNormal(TriMesh *&_mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a vertex normal.
void updateFaceNormalsOfOpenMesh(MeshT *&_mesh)
Updates face normals.
MeshT * mesh()
return a pointer to the mesh
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
bool is_valid() const
The handle is valid iff the index is not negative.
int idx() const
Get the underlying index of this handle.
VertexHandle add_vertex(const VecT &_p)
Add a geometric point to the mesh.
const VecT & vertex(VertexHandle _vh) const
Get point _vh's coordinates.
PointT normal(HalfFaceHandle _hfh) const
size_t valence(VertexHandle _vh) const
Get valence of vertex (number of incident edges)
const Cell & cell(CellHandle _cellHandle) const
Get cell with handle _cellHandle.
bool is_valid(Handle _h) const
test is_valid and perform index range check
HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get previous halfedge within a halfface.
HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get next halfedge within a halfface.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
size_t n_vertices() const override
Get number of vertices in mesh.
virtual FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false)
Add face via incident edges.
static HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_faces() const override
Get number of faces in mesh.
virtual CellHandle add_cell(std::vector< HalfFaceHandle > _halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
Face halfface(HalfFaceHandle _halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
const Edge & edge(EdgeHandle _edgeHandle) const
Get edge with handle _edgeHandle.
HalfFaceHandle adjacent_halfface_in_cell(HalfFaceHandle _halfFaceHandle, HalfEdgeHandle _halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell. It correctly handles s...
const Face & face(FaceHandle _faceHandle) const
Get face with handle _faceHandle.
Type for a Meshobject containing a poly mesh.
Type for a MeshObject containing a triangle mesh.
MeshT * mesh()
return a pointer to the mesh
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
bool getMesh(int _identifier, PolyMesh *&_mesh)
Get the Poly Mesh which has the given identifier.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
TetrahedralMesh * tetrahedralMesh(BaseObjectData *_object)
Get an TetrahedralMesh from an object.
Handle for a face entity.
PolyConnectivity::ConstFaceEdgeRange edges() const
Returns a range of edges of the face (PolyConnectivity::fv_range())
Handle for a vertex entity.