31 SmartPointer<Mesh<T>> mesh =
nullptr;
34 std::unordered_map<std::string, std::vector<double>> metaData;
36#ifdef VIENNALS_USE_VTK
38 vtkPolyData *inputPolyData =
nullptr;
39 vtkUnstructuredGrid *inputUnstructuredGrid =
nullptr;
42 unsigned vtk_nodes_for_cell_type[15] = {0, 1, 0, 2, 0, 3, 0, 0,
46 void extractFieldData(vtkDataSet *data) {
47 vtkFieldData *fieldData = data->GetFieldData();
51 for (
int i = 0; i < fieldData->GetNumberOfArrays(); ++i) {
52 vtkDataArray *array = fieldData->GetArray(i);
56 const char *name = array->GetName();
60 int numTuples = array->GetNumberOfTuples();
61 int numComponents = array->GetNumberOfComponents();
63 std::vector<T> values;
64 values.reserve(numTuples * numComponents);
66 for (
int t = 0; t < numTuples; ++t) {
68 array->GetTuple(t, tuple);
69 for (
int c = 0; c < numComponents; ++c)
70 values.push_back(tuple[c]);
73 metaData[name] = std::move(values);
83 : mesh(passedMesh), fileName(std::move(passedFileName)) {}
86 std::string passedFileName)
87 : mesh(passedMesh), fileFormat(passedFormat),
88 fileName(std::move(passedFileName)) {}
90#ifdef VIENNALS_USE_VTK
93 : mesh(passedMesh), inputPolyData(polyData) {
98 VTKReader(SmartPointer<Mesh<T>> passedMesh,
99 vtkUnstructuredGrid *unstructuredGrid)
100 : mesh(passedMesh), inputUnstructuredGrid(unstructuredGrid) {
113 fileName = std::move(passedFileName);
116#ifdef VIENNALS_USE_VTK
118 void setPolyData(vtkPolyData *polyData) {
119 inputPolyData = polyData;
120 inputUnstructuredGrid =
nullptr;
126 void setUnstructuredGrid(vtkUnstructuredGrid *unstructuredGrid) {
127 inputUnstructuredGrid = unstructuredGrid;
128 inputPolyData =
nullptr;
138 if (mesh ==
nullptr) {
139 Logger::getInstance()
140 .addError(
"No mesh was passed to VTKReader.")
145#ifdef VIENNALS_USE_VTK
147 if (inputPolyData !=
nullptr) {
148 buildFromPolyData(inputPolyData);
152 if (inputUnstructuredGrid !=
nullptr) {
153 buildFromUnstructuredGrid(inputUnstructuredGrid);
159 if (fileName.empty()) {
160 Logger::getInstance()
161 .addError(
"No file name specified for VTKReader.")
167 auto dotPos = fileName.rfind(
'.');
168 if (dotPos == std::string::npos) {
169 Logger::getInstance()
170 .addError(
"No valid file format found based on the file ending "
171 "passed to VTKReader.")
175 auto ending = fileName.substr(dotPos);
176 if (ending ==
".vtk") {
178 }
else if (ending ==
".vtp") {
180 }
else if (ending ==
".vtu") {
183 Logger::getInstance()
184 .addError(
"No valid file format found based on the file ending "
185 "passed to VTKReader.")
192 switch (fileFormat) {
194 readVTKLegacy(fileName);
196#ifdef VIENNALS_USE_VTK
206 Logger::getInstance()
207 .addError(
"VTKReader was built without VTK support. Only VTK_LEGACY "
212 Logger::getInstance()
213 .addError(
"No valid file format set for VTKReader.")
219#ifdef VIENNALS_USE_VTK
221 void buildFromPolyData(vtkPolyData *polyData) {
223 Logger::getInstance()
224 .addError(
"Null vtkPolyData passed to VTKReader.")
231 mesh->nodes.resize(polyData->GetNumberOfPoints());
232 for (
unsigned i = 0; i < mesh->nodes.size(); ++i) {
233 std::array<double, 3> coords{};
234 polyData->GetPoint(i, coords.data());
235 mesh->nodes[i] = coords;
238 vtkSmartPointer<vtkCellArray> cellArray =
239 vtkSmartPointer<vtkCellArray>::New();
242 mesh->vertices.reserve(polyData->GetNumberOfVerts());
243 cellArray = polyData->GetVerts();
244 cellArray->InitTraversal();
245 vtkIdList *pointList = vtkIdList::New();
246 while (cellArray->GetNextCell(pointList)) {
247 std::array<unsigned, 1> cell{};
248 cell[0] = pointList->GetId(0);
249 mesh->vertices.push_back(cell);
255 mesh->lines.reserve(polyData->GetNumberOfLines());
256 cellArray = polyData->GetLines();
257 cellArray->InitTraversal();
258 vtkIdList *pointList = vtkIdList::New();
259 while (cellArray->GetNextCell(pointList)) {
260 std::array<unsigned, 2> cell{};
261 for (
unsigned i = 0; i < 2; ++i) {
262 cell[i] = pointList->GetId(i);
264 mesh->lines.push_back(cell);
270 mesh->triangles.reserve(polyData->GetNumberOfPolys());
271 cellArray = polyData->GetPolys();
272 cellArray->InitTraversal();
273 vtkIdList *pointList = vtkIdList::New();
274 while (cellArray->GetNextCell(pointList)) {
275 std::array<unsigned, 3> cell{};
276 for (
unsigned i = 0; i < 3; ++i) {
277 cell[i] = pointList->GetId(i);
279 mesh->triangles.push_back(cell);
284 vtkSmartPointer<vtkPointData> pointData =
285 vtkSmartPointer<vtkPointData>::New();
286 pointData = polyData->GetPointData();
288 for (
int i = 0; i < static_cast<int>(pointData->GetNumberOfArrays()); ++i) {
289 if (vtkDataArray *dataArray = pointData->GetArray(i);
290 dataArray->GetNumberOfComponents() == 1) {
291 mesh->pointData.insertNextScalarData(
292 typename PointData<T>::ScalarDataType(),
293 std::string(pointData->GetArrayName(i)));
294 auto &scalars = *(mesh->pointData.getScalarData(i));
295 scalars.resize(pointData->GetNumberOfTuples());
296 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
297 scalars[j] = dataArray->GetTuple1(j);
299 }
else if (dataArray->GetNumberOfComponents() == 3) {
300 mesh->pointData.insertNextVectorData(
301 typename PointData<T>::VectorDataType(),
302 std::string(pointData->GetArrayName(i)));
303 auto &vectors = *(mesh->pointData.getVectorData(i));
304 vectors.resize(pointData->GetNumberOfTuples());
305 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
306 std::array<double, 3> vector{};
307 dataArray->GetTuple(j, &(vector[0]));
314 vtkSmartPointer<vtkCellData> cellData = vtkSmartPointer<vtkCellData>::New();
315 cellData = polyData->GetCellData();
317 for (
int i = 0; i < cellData->GetNumberOfArrays(); ++i) {
318 vtkDataArray *dataArray = cellData->GetArray(i);
319 if (cellData->GetNumberOfComponents() == 1) {
320 mesh->cellData.insertNextScalarData(
321 typename PointData<T>::ScalarDataType(),
322 std::string(cellData->GetArrayName(i)));
323 auto &scalars = *(mesh->cellData.getScalarData(i));
324 scalars.resize(cellData->GetNumberOfTuples());
325 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
326 scalars[j] = dataArray->GetTuple1(j);
328 }
else if (cellData->GetNumberOfComponents() == 3) {
329 mesh->cellData.insertNextVectorData(
330 typename PointData<T>::VectorDataType(),
331 std::string(cellData->GetArrayName(i)));
332 auto &vectors = *(mesh->cellData.getVectorData(i));
333 vectors.resize(cellData->GetNumberOfTuples());
334 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
335 std::array<double, 3> vector{};
336 dataArray->GetTuple(j, &(vector[0]));
343 extractFieldData(polyData);
346 void readVTP(
const std::string &filename) {
349 vtkSmartPointer<vtkXMLPolyDataReader> pReader =
350 vtkSmartPointer<vtkXMLPolyDataReader>::New();
351 pReader->SetFileName(filename.c_str());
354 vtkSmartPointer<vtkPolyData> polyData = pReader->GetOutput();
355 buildFromPolyData(polyData);
359 void buildFromUnstructuredGrid(vtkUnstructuredGrid *ugrid) {
361 Logger::getInstance()
362 .addError(
"Null vtkUnstructuredGrid passed to VTKReader.")
370 mesh->nodes.resize(ugrid->GetNumberOfPoints());
371 for (
unsigned i = 0; i < mesh->nodes.size(); ++i) {
372 std::array<double, 3> coords{};
373 ugrid->GetPoint(i, &(coords[0]));
374 mesh->nodes[i] = coords;
378 for (
unsigned i = 0; i < ugrid->GetNumberOfCells(); ++i) {
379 vtkIdList *pointList = vtkIdList::New();
380 ugrid->GetCellPoints(i, pointList);
382 switch (ugrid->GetCellType(i)) {
385 std::array<unsigned, 1> vert{};
386 vert[0] = pointList->GetId(0);
387 mesh->vertices.push_back(vert);
391 std::array<unsigned, 2> elements{};
392 for (
unsigned j = 0; j < 2; ++j) {
393 elements[j] = pointList->GetId(j);
395 mesh->lines.push_back(elements);
399 std::array<unsigned, 3> elements{};
400 for (
unsigned j = 0; j < 3; ++j) {
401 elements[j] = pointList->GetId(j);
403 mesh->triangles.push_back(elements);
407 std::array<unsigned, 4> elements{};
408 for (
unsigned j = 0; j < 4; ++j) {
409 elements[j] = pointList->GetId(j);
411 mesh->tetras.push_back(elements);
415 std::array<unsigned, 8> elements{};
416 for (
unsigned j = 0; j < 8; ++j) {
417 elements[j] = pointList->GetId(j);
419 mesh->hexas.push_back(elements);
425 vtkSmartPointer<vtkPointData> pointData =
426 vtkSmartPointer<vtkPointData>::New();
427 pointData = ugrid->GetPointData();
429 for (
int i = 0; i < pointData->GetNumberOfArrays(); ++i) {
430 if (vtkDataArray *dataArray = pointData->GetArray(i);
431 dataArray->GetNumberOfComponents() == 1) {
432 mesh->pointData.insertNextScalarData(
433 typename PointData<T>::ScalarDataType(),
434 std::string(pointData->GetArrayName(i)));
435 auto &scalars = *(mesh->pointData.getScalarData(i));
436 scalars.resize(pointData->GetNumberOfTuples());
437 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
438 scalars[j] = dataArray->GetTuple1(j);
440 }
else if (dataArray->GetNumberOfComponents() == 3) {
441 mesh->pointData.insertNextVectorData(
442 typename PointData<T>::VectorDataType(),
443 std::string(pointData->GetArrayName(i)));
444 auto &vectors = *(mesh->pointData.getVectorData(i));
445 vectors.resize(pointData->GetNumberOfTuples());
446 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
447 std::array<double, 3> vector{};
448 dataArray->GetTuple(j, &(vector[0]));
455 vtkSmartPointer<vtkCellData> cellData = vtkSmartPointer<vtkCellData>::New();
456 cellData = ugrid->GetCellData();
458 for (
int i = 0; i < static_cast<int>(cellData->GetNumberOfArrays()); ++i) {
459 vtkDataArray *dataArray = cellData->GetArray(i);
460 if (cellData->GetNumberOfComponents() == 1) {
461 mesh->cellData.insertNextScalarData(
462 typename PointData<T>::ScalarDataType(),
463 std::string(cellData->GetArrayName(i)));
464 auto &scalars = *(mesh->cellData.getScalarData(i));
465 scalars.resize(cellData->GetNumberOfTuples());
466 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
467 scalars[j] = dataArray->GetTuple1(j);
469 }
else if (cellData->GetNumberOfComponents() == 3) {
470 mesh->cellData.insertNextVectorData(
471 typename PointData<T>::VectorDataType(),
472 std::string(cellData->GetArrayName(i)));
473 auto &vectors = *(mesh->cellData.getVectorData(i));
474 vectors.resize(cellData->GetNumberOfTuples());
475 for (
unsigned j = 0; j < dataArray->GetNumberOfTuples(); ++j) {
476 std::array<double, 3> vector{};
477 dataArray->GetTuple(j, &(vector[0]));
484 extractFieldData(ugrid);
487 void readVTU(
const std::string &filename) {
491 vtkSmartPointer<vtkXMLUnstructuredGridReader> greader =
492 vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
493 greader->SetFileName(filename.c_str());
496 vtkSmartPointer<vtkUnstructuredGrid> ugrid = greader->GetOutput();
497 buildFromUnstructuredGrid(ugrid);
502 void readVTKLegacy(
const std::string &filename) {
506 std::ifstream f(filename.c_str());
508 Logger::getInstance().addError(
"Could not open geometry file!");
512 while (std::getline(f, temp)) {
513 if (temp.find(
"DATASET") != std::string::npos)
516 if (temp.find(
"UNSTRUCTURED_GRID") == std::string::npos) {
517 Logger::getInstance().addError(
"DATASET is not an UNSTRUCTURED_GRID!");
521 while (std::getline(f, temp)) {
522 if (temp.find(
"POINTS") != std::string::npos)
525 int num_nodes = atoi(&temp[temp.find(
' ') + 1]);
527 mesh->nodes.resize(num_nodes);
529 for (
int i = 0; i < num_nodes; i++) {
532 for (
double &coord : coords)
534 for (
int j = 0; j < 3; j++) {
535 mesh->nodes[i][j] = coords[j];
547 while (std::getline(f, temp)) {
548 if (temp.find(
"CELLS") == 0)
552 int num_elems = atoi(&temp[temp.find(
' ') + 1]);
554 std::ifstream f_ct(filename.c_str());
559 while (std::getline(f_ct, temp)) {
560 if (temp.find(
"CELL_TYPES") == 0)
563 int num_cell_types = atoi(&temp[temp.find(
' ') + 1]);
565 if (num_elems != num_cell_types) {
566 Logger::getInstance().addError(
567 "Corrupt input geometry! Number of CELLS and CELL_TYPES "
571 bool is_material =
true;
573 while (std::getline(f_m, temp)) {
574 if (temp.find(
"CELL_DATA") != std::string::npos) {
575 std::getline(f_m, temp);
576 if ((temp.find(
"SCALARS material") != std::string::npos) ||
577 (temp.find(
"SCALARS Material") != std::string::npos)) {
578 std::getline(f_m, temp);
588 std::vector<VectorType<unsigned int, 4>> elements;
589 elements.reserve(num_elems);
591 std::vector<double> materials;
595 unsigned cell_material;
596 for (
int i = 0; i < num_elems; i++) {
600 f_m >> cell_material;
606 unsigned number_nodes = vtk_nodes_for_cell_type[cell_type];
607 if (number_nodes == elems_fake || number_nodes == 0) {
611 std::array<unsigned, 1> elem{};
613 mesh->template getElements<1>().push_back(elem);
614 materials.push_back(cell_material);
618 std::array<unsigned, 2> elem{};
619 for (
unsigned j = 0; j < number_nodes; ++j) {
622 mesh->template getElements<2>().push_back(elem);
623 materials.push_back(cell_material);
628 std::array<unsigned, 3> elem{};
629 for (
unsigned j = 0; j < number_nodes; ++j) {
632 mesh->template getElements<3>().push_back(elem);
633 materials.push_back(cell_material);
639 std::array<unsigned, 4> elem{};
640 for (
unsigned j = 0; j < number_nodes; ++j) {
643 mesh->template getElements<4>().push_back(elem);
644 materials.push_back(cell_material);
650 std::array<unsigned, 3> elem{};
651 for (
unsigned j = 0; j < 3; ++j) {
654 mesh->template getElements<3>().push_back(
656 materials.push_back(cell_material);
659 mesh->template getElements<3>().push_back(elem);
660 materials.push_back(cell_material);
665 std::ostringstream oss;
666 oss <<
"VTK Cell type " << cell_type
667 <<
" is not supported. Cell ignored..." << std::endl;
668 VIENNACORE_LOG_WARNING(oss.str());
671 std::ostringstream oss;
672 oss <<
"INVALID CELL TYPE! Expected number of nodes: " << number_nodes
673 <<
", Found number of nodes: " << elems_fake
674 <<
"; Ignoring element...";
675 VIENNACORE_LOG_ERROR(oss.str());
677 f.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
681 mesh->cellData.insertNextScalarData(materials,
"Material");
684 int num_cell_data = 0;
685 while (std::getline(f, temp)) {
686 if (temp.find(
"CELL_DATA") != std::string::npos) {
687 num_cell_data = atoi(&temp[temp.find(
' ') + 1]);
691 std::cout <<
"Read cell data: " << num_cell_data << std::endl;
694 std::cout <<
"reading scalar data" << std::endl;
695 while (std::getline(f, temp)) {
696 if (temp.find(
"SCALARS") != std::string::npos)
703 std::string scalarDataName;
705 auto firstS = temp.find(
' ') + 1;
706 auto secondS = temp.find(
' ', firstS + 1);
707 scalarDataName = temp.substr(firstS, secondS - firstS);
709 std::vector<double> scalarData;
712 std::getline(f, temp);
713 if (temp !=
"LOOKUP_TABLE default") {
714 VIENNACORE_LOG_WARNING(
"Wrong lookup table for VTKLegacy: " + temp);
718 for (
int i = 0; i < num_cell_data; ++i) {
721 scalarData.push_back(data);
724 mesh->cellData.insertNextScalarData(scalarData, scalarDataName);