34 using MetaDataType = std::unordered_map<std::string, std::vector<double>>;
36 SmartPointer<Mesh<T>> mesh =
nullptr;
39 MetaDataType metaData;
41#ifdef VIENNALS_USE_VTK
42 template <
class In,
class Out>
43 void addDataFromMesh(
const In &inData, Out outData)
const {
45 for (
unsigned i = 0; i < inData.getScalarDataSize(); ++i) {
46 vtkSmartPointer<vtkFloatArray> pointData =
47 vtkSmartPointer<vtkFloatArray>::New();
48 pointData->SetNumberOfComponents(1);
49 pointData->SetName(inData.getScalarDataLabel(i).c_str());
50 auto scalars = *(inData.getScalarData(i));
51 for (
unsigned j = 0; j < inData.getScalarData(i)->size(); ++j) {
52 pointData->InsertNextValue(scalars[j]);
54 outData->AddArray(pointData);
58 for (
unsigned i = 0; i < inData.getVectorDataSize(); ++i) {
59 vtkSmartPointer<vtkFloatArray> vectorData =
60 vtkSmartPointer<vtkFloatArray>::New();
61 vectorData->SetNumberOfComponents(3);
62 vectorData->SetName(inData.getVectorDataLabel(i).c_str());
63 auto vectors = *(inData.getVectorData(i));
64 for (
unsigned j = 0; j < inData.getVectorData(i)->size(); ++j) {
65 vectorData->InsertNextTuple3(vectors[j][0], vectors[j][1],
68 outData->AddArray(vectorData);
72 void addMetaDataToVTK(vtkDataSet *data)
const {
73 if (metaData.empty()) {
78 vtkSmartPointer<vtkFieldData> fieldData = data->GetFieldData();
79 for (
const auto &meta : metaData) {
80 if (meta.second.empty())
83 vtkSmartPointer<vtkFloatArray> metaDataArray =
84 vtkSmartPointer<vtkFloatArray>::New();
85 metaDataArray->SetName(meta.first.c_str());
86 metaDataArray->SetNumberOfValues(meta.second.size());
87 for (
size_t i = 0; i < meta.second.size(); ++i) {
88 metaDataArray->SetValue(i, meta.second[i]);
90 fieldData->AddArray(metaDataArray);
101 : mesh(passedMesh), fileName(std::move(passedFileName)) {}
104 std::string passedFileName)
105 : mesh(passedMesh), fileFormat(passedFormat),
106 fileName(std::move(passedFileName)) {}
115 fileName = std::move(passedFileName);
119 metaData = passedMetaData;
123 metaData[key] = std::vector<double>{value};
126 void addMetaData(
const std::string &key,
const std::vector<double> &values) {
127 metaData[key] = values;
131 for (
const auto &pair : newMetaData) {
132 metaData[pair.first] = pair.second;
138 if (mesh ==
nullptr) {
139 Logger::getInstance()
140 .addError(
"No mesh was passed to VTKWriter.")
145 if (fileName.empty()) {
146 Logger::getInstance()
147 .addError(
"No file name specified for VTKWriter.")
151 if (mesh->nodes.empty()) {
152 Logger::getInstance().addWarning(
"Writing empty mesh.").print();
157 auto dotPos = fileName.rfind(
'.');
158 if (dotPos == std::string::npos) {
161 auto ending = fileName.substr(dotPos);
162 if (ending ==
".vtk") {
164 }
else if (ending ==
".vtp") {
166 }
else if (ending ==
".vtu") {
169 Logger::getInstance()
170 .addError(
"No valid file format found based on the file ending "
171 "passed to VTKWriter.")
179 switch (fileFormat) {
181 writeVTKLegacy(fileName);
183#ifdef VIENNALS_USE_VTK
193 Logger::getInstance()
194 .addWarning(
"VTKWriter was built without VTK support. Falling back "
197 writeVTKLegacy(fileName);
201 Logger::getInstance()
202 .addError(
"No valid file format set for VTKWriter.")
208#ifdef VIENNALS_USE_VTK
209 void writeVTP(std::string filename)
const {
210 if (mesh ==
nullptr) {
211 Logger::getInstance()
212 .addError(
"No mesh was passed to VTKWriter.")
217 if (filename.find(
".vtp") != filename.size() - 4)
219 vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
222 vtkSmartPointer<vtkPoints> polyPoints = vtkSmartPointer<vtkPoints>::New();
223 for (
auto it = mesh->getNodes().begin(); it != mesh->getNodes().end();
225 polyPoints->InsertNextPoint((*it)[0], (*it)[1], (*it)[2]);
227 polyData->SetPoints(polyPoints);
230 if (mesh->vertices.size() > 0) {
231 vtkSmartPointer<vtkCellArray> polyCells =
232 vtkSmartPointer<vtkCellArray>::New();
233 for (
auto it = mesh->vertices.begin(); it != mesh->vertices.end(); ++it) {
234 polyCells->InsertNextCell(1);
235 polyCells->InsertCellPoint((*it)[0]);
237 polyData->SetVerts(polyCells);
241 if (mesh->lines.size() > 0) {
242 vtkSmartPointer<vtkCellArray> polyCells =
243 vtkSmartPointer<vtkCellArray>::New();
244 for (
auto it = mesh->lines.begin(); it != mesh->lines.end(); ++it) {
245 polyCells->InsertNextCell(2);
246 for (
unsigned i = 0; i < 2; ++i) {
247 polyCells->InsertCellPoint((*it)[i]);
250 polyData->SetLines(polyCells);
254 if (mesh->triangles.size() > 0) {
255 vtkSmartPointer<vtkCellArray> polyCells =
256 vtkSmartPointer<vtkCellArray>::New();
257 for (
auto it = mesh->triangles.begin(); it != mesh->triangles.end();
259 polyCells->InsertNextCell(3);
260 for (
unsigned i = 0; i < 3; ++i) {
261 polyCells->InsertCellPoint((*it)[i]);
264 polyData->SetPolys(polyCells);
267 addDataFromMesh(mesh->pointData, polyData->GetPointData());
268 addDataFromMesh(mesh->cellData, polyData->GetCellData());
269 addMetaDataToVTK(polyData);
271 vtkSmartPointer<vtkXMLPolyDataWriter> pwriter =
272 vtkSmartPointer<vtkXMLPolyDataWriter>::New();
273 pwriter->SetFileName(filename.c_str());
274 pwriter->SetInputData(polyData);
278 void writeVTU(std::string filename)
const {
279 if (mesh ==
nullptr) {
280 Logger::getInstance()
281 .addError(
"No mesh was passed to VTKWriter.")
286 if (filename.find(
".vtu") != filename.size() - 4)
289 vtkSmartPointer<vtkUnstructuredGrid> uGrid =
290 vtkSmartPointer<vtkUnstructuredGrid>::New();
293 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
294 for (
auto it = mesh->getNodes().begin(); it != mesh->getNodes().end();
296 points->InsertNextPoint((*it)[0], (*it)[1], (*it)[2]);
298 uGrid->SetPoints(points);
301 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
302 std::vector<int> cellTypes;
303 cellTypes.reserve(mesh->vertices.size() + mesh->lines.size() +
304 mesh->triangles.size() + mesh->tetras.size() +
308 if (mesh->vertices.size() > 0) {
309 for (
auto it = mesh->vertices.begin(); it != mesh->vertices.end(); ++it) {
310 cells->InsertNextCell(1);
311 cells->InsertCellPoint((*it)[0]);
312 cellTypes.push_back(1);
317 if (mesh->lines.size() > 0) {
318 for (
auto it = mesh->lines.begin(); it != mesh->lines.end(); ++it) {
319 cells->InsertNextCell(2);
320 for (
unsigned i = 0; i < 2; ++i) {
321 cells->InsertCellPoint((*it)[i]);
323 cellTypes.push_back(3);
328 if (mesh->triangles.size() > 0) {
329 for (
auto it = mesh->triangles.begin(); it != mesh->triangles.end();
331 cells->InsertNextCell(3);
332 for (
unsigned i = 0; i < 3; ++i) {
333 cells->InsertCellPoint((*it)[i]);
335 cellTypes.push_back(5);
340 if (mesh->tetras.size() > 0) {
341 for (
auto it = mesh->tetras.begin(); it != mesh->tetras.end(); ++it) {
342 cells->InsertNextCell(4);
343 for (
unsigned i = 0; i < 4; ++i) {
344 cells->InsertCellPoint((*it)[i]);
346 cellTypes.push_back(10);
351 if (mesh->hexas.size() > 0) {
352 for (
auto it = mesh->hexas.begin(); it != mesh->hexas.end(); ++it) {
353 cells->InsertNextCell(8);
354 for (
unsigned i = 0; i < 8; ++i) {
355 cells->InsertCellPoint((*it)[i]);
357 cellTypes.push_back(12);
362 uGrid->SetCells(&(cellTypes[0]), cells);
364 addDataFromMesh(mesh->pointData, uGrid->GetPointData());
365 addDataFromMesh(mesh->cellData, uGrid->GetCellData());
366 addMetaDataToVTK(uGrid);
395 vtkSmartPointer<vtkXMLUnstructuredGridWriter> owriter =
396 vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
397 owriter->SetFileName(filename.c_str());
398 owriter->SetInputData(uGrid);
404 void writeVTKLegacy(
const std::string &filename) {
405 if (mesh ==
nullptr) {
406 Logger::getInstance()
407 .addError(
"No mesh was passed to VTKWriter.")
412 std::ofstream f(filename.c_str());
414 f <<
"# vtk DataFile Version 2.0" << std::endl;
415 f << ((!mesh->lines.empty()) ? 2 : 3) <<
"D Surface" << std::endl;
416 f <<
"ASCII" << std::endl;
417 f <<
"DATASET UNSTRUCTURED_GRID" << std::endl;
418 f <<
"POINTS " << mesh->nodes.size() <<
" float" << std::endl;
421 for (
unsigned int i = 0; i < mesh->nodes.size(); i++) {
422 for (
int j = 0; j < 3; j++)
423 f <<
static_cast<float>(mesh->nodes[i][j]) <<
" ";
427 const unsigned numberOfCells = mesh->vertices.size() + mesh->lines.size() +
428 mesh->triangles.size() +
429 mesh->tetras.size() + mesh->hexas.size();
430 const unsigned cellDataSize =
431 2 * mesh->vertices.size() + 3 * mesh->lines.size() +
432 4 * mesh->triangles.size() + 5 * mesh->tetras.size() +
433 9 * mesh->hexas.size();
435 f <<
"CELLS " << numberOfCells <<
" " << cellDataSize << std::endl;
438 for (
unsigned int i = 0; i < mesh->vertices.size(); i++) {
439 f << 1 <<
" " << mesh->vertices[i][0] << std::endl;
441 for (
unsigned int i = 0; i < mesh->lines.size(); i++) {
443 for (
int j = 0; j < 2; j++)
444 f << mesh->lines[i][j] <<
" ";
448 for (
unsigned int i = 0; i < mesh->triangles.size(); i++) {
450 for (
int j = 0; j < 3; j++)
451 f << mesh->triangles[i][j] <<
" ";
455 for (
unsigned int i = 0; i < mesh->tetras.size(); i++) {
457 for (
int j = 0; j < 4; j++)
458 f << mesh->tetras[i][j] <<
" ";
462 for (
unsigned int i = 0; i < mesh->hexas.size(); i++) {
464 for (
int j = 0; j < 8; j++)
465 f << mesh->hexas[i][j] <<
" ";
469 f <<
"CELL_TYPES " << numberOfCells << std::endl;
470 for (
unsigned i = 0; i < mesh->vertices.size(); ++i)
473 for (
unsigned i = 0; i < mesh->lines.size(); ++i)
476 for (
unsigned i = 0; i < mesh->triangles.size(); ++i)
479 for (
unsigned i = 0; i < mesh->tetras.size(); ++i)
480 f << 10 << std::endl;
482 for (
unsigned i = 0; i < mesh->hexas.size(); ++i)
483 f << 12 << std::endl;
486 if (mesh->pointData.getScalarDataSize() ||
487 mesh->pointData.getVectorDataSize()) {
488 Logger::getInstance()
489 .addWarning(
"Point data output not supported for legacy VTK output. "
490 "Point data is ignored.")
495 if (mesh->cellData.getScalarDataSize()) {
496 f <<
"CELL_DATA " << mesh->cellData.getScalarData(0)->size() << std::endl;
497 for (
unsigned i = 0; i < mesh->cellData.getScalarDataSize(); ++i) {
498 auto scalars = *(mesh->cellData.getScalarData(i));
499 f <<
"SCALARS " << mesh->cellData.getScalarDataLabel(i) <<
" float"
501 f <<
"LOOKUP_TABLE default" << std::endl;
502 for (
unsigned j = 0; j < scalars.size(); ++j) {
503 f << ((std::abs(scalars[j]) < 1e-6) ? 0.0 : scalars[j]) << std::endl;
509 if (mesh->cellData.getVectorDataSize()) {
510 if (!mesh->cellData.getScalarDataSize())
511 f <<
"CELL_DATA " << mesh->cellData.getVectorData(0)->size()
513 for (
unsigned i = 0; i < mesh->cellData.getVectorDataSize(); ++i) {
514 auto vectors = *(mesh->cellData.getVectorData(i));
515 f <<
"VECTORS " << mesh->cellData.getVectorDataLabel(i) <<
" float"
517 for (
unsigned j = 0; j < vectors.size(); ++j) {
518 for (
unsigned k = 0; k < 3; ++k) {
519 f << vectors[j][k] <<
" ";