34 SmartPointer<Mesh<T>> mesh =
nullptr;
37 std::unordered_map<std::string, std::vector<T>> metaData;
39#ifdef VIENNALS_USE_VTK
40 template <
class In,
class Out>
41 void addDataFromMesh(
const In &inData, Out outData)
const {
43 for (
unsigned i = 0; i < inData.getScalarDataSize(); ++i) {
44 vtkSmartPointer<vtkFloatArray> pointData =
45 vtkSmartPointer<vtkFloatArray>::New();
46 pointData->SetNumberOfComponents(1);
47 pointData->SetName(inData.getScalarDataLabel(i).c_str());
48 auto scalars = *(inData.getScalarData(i));
49 for (
unsigned j = 0; j < inData.getScalarData(i)->size(); ++j) {
50 pointData->InsertNextValue(scalars[j]);
52 outData->AddArray(pointData);
56 for (
unsigned i = 0; i < inData.getVectorDataSize(); ++i) {
57 vtkSmartPointer<vtkFloatArray> vectorData =
58 vtkSmartPointer<vtkFloatArray>::New();
59 vectorData->SetNumberOfComponents(3);
60 vectorData->SetName(inData.getVectorDataLabel(i).c_str());
61 auto vectors = *(inData.getVectorData(i));
62 for (
unsigned j = 0; j < inData.getVectorData(i)->size(); ++j) {
63 vectorData->InsertNextTuple3(vectors[j][0], vectors[j][1],
66 outData->AddArray(vectorData);
70 void addMetaDataToVTK(vtkDataSet *data)
const {
71 if (metaData.empty()) {
76 vtkSmartPointer<vtkFieldData> fieldData = data->GetFieldData();
77 for (
const auto &meta : metaData) {
78 if (meta.second.empty())
81 vtkSmartPointer<vtkFloatArray> metaDataArray =
82 vtkSmartPointer<vtkFloatArray>::New();
83 metaDataArray->SetName(meta.first.c_str());
84 metaDataArray->SetNumberOfValues(meta.second.size());
85 for (
size_t i = 0; i < meta.second.size(); ++i) {
86 metaDataArray->SetValue(i, meta.second[i]);
88 fieldData->AddArray(metaDataArray);
99 : mesh(passedMesh), fileName(std::move(passedFileName)) {}
102 std::string passedFileName)
103 : mesh(passedMesh), fileFormat(passedFormat),
104 fileName(std::move(passedFileName)) {}
113 fileName = std::move(passedFileName);
117 const std::unordered_map<std::string, std::vector<T>> &passedMetaData) {
118 metaData = passedMetaData;
122 metaData[key] = std::vector<T>{value};
125 void addMetaData(
const std::string &key,
const std::vector<T> &values) {
126 metaData[key] = values;
130 const std::unordered_map<std::string, std::vector<T>> &newMetaData) {
131 for (
const auto &pair : newMetaData) {
132 metaData[pair.first] = pair.second;
138 if (mesh ==
nullptr) {
139 Logger::getInstance()
140 .addWarning(
"No mesh was passed to VTKWriter. Not writing.")
145 if (fileName.empty()) {
146 Logger::getInstance()
147 .addWarning(
"No file name specified for VTKWriter. Not writing.")
153 auto dotPos = fileName.rfind(
'.');
154 if (dotPos == std::string::npos) {
157 auto ending = fileName.substr(dotPos);
158 if (ending ==
".vtk") {
160 }
else if (ending ==
".vtp") {
162 }
else if (ending ==
".vtu") {
165 Logger::getInstance()
166 .addWarning(
"No valid file format found based on the file ending "
167 "passed to VTKWriter. Not writing.")
175 switch (fileFormat) {
177 writeVTKLegacy(fileName);
179#ifdef VIENNALS_USE_VTK
189 Logger::getInstance()
190 .addWarning(
"VTKWriter was built without VTK support. Falling back "
193 writeVTKLegacy(fileName);
197 Logger::getInstance()
198 .addWarning(
"No valid file format set for VTKWriter. Not writing.")
204#ifdef VIENNALS_USE_VTK
205 void writeVTP(std::string filename)
const {
206 if (mesh ==
nullptr) {
207 Logger::getInstance()
208 .addWarning(
"No mesh was passed to VTKWriter.")
213 if (filename.find(
".vtp") != filename.size() - 4)
215 vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
218 vtkSmartPointer<vtkPoints> polyPoints = vtkSmartPointer<vtkPoints>::New();
219 for (
auto it = mesh->getNodes().begin(); it != mesh->getNodes().end();
221 polyPoints->InsertNextPoint((*it)[0], (*it)[1], (*it)[2]);
223 polyData->SetPoints(polyPoints);
226 if (mesh->vertices.size() > 0) {
227 vtkSmartPointer<vtkCellArray> polyCells =
228 vtkSmartPointer<vtkCellArray>::New();
229 for (
auto it = mesh->vertices.begin(); it != mesh->vertices.end(); ++it) {
230 polyCells->InsertNextCell(1);
231 polyCells->InsertCellPoint((*it)[0]);
233 polyData->SetVerts(polyCells);
237 if (mesh->lines.size() > 0) {
238 vtkSmartPointer<vtkCellArray> polyCells =
239 vtkSmartPointer<vtkCellArray>::New();
240 for (
auto it = mesh->lines.begin(); it != mesh->lines.end(); ++it) {
241 polyCells->InsertNextCell(2);
242 for (
unsigned i = 0; i < 2; ++i) {
243 polyCells->InsertCellPoint((*it)[i]);
246 polyData->SetLines(polyCells);
250 if (mesh->triangles.size() > 0) {
251 vtkSmartPointer<vtkCellArray> polyCells =
252 vtkSmartPointer<vtkCellArray>::New();
253 for (
auto it = mesh->triangles.begin(); it != mesh->triangles.end();
255 polyCells->InsertNextCell(3);
256 for (
unsigned i = 0; i < 3; ++i) {
257 polyCells->InsertCellPoint((*it)[i]);
260 polyData->SetPolys(polyCells);
263 addDataFromMesh(mesh->pointData, polyData->GetPointData());
264 addDataFromMesh(mesh->cellData, polyData->GetCellData());
265 addMetaDataToVTK(polyData);
267 vtkSmartPointer<vtkXMLPolyDataWriter> pwriter =
268 vtkSmartPointer<vtkXMLPolyDataWriter>::New();
269 pwriter->SetFileName(filename.c_str());
270 pwriter->SetInputData(polyData);
274 void writeVTU(std::string filename)
const {
275 if (mesh ==
nullptr) {
276 Logger::getInstance()
277 .addWarning(
"No mesh was passed to VTKWriter.")
282 if (filename.find(
".vtu") != filename.size() - 4)
285 vtkSmartPointer<vtkUnstructuredGrid> uGrid =
286 vtkSmartPointer<vtkUnstructuredGrid>::New();
289 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
290 for (
auto it = mesh->getNodes().begin(); it != mesh->getNodes().end();
292 points->InsertNextPoint((*it)[0], (*it)[1], (*it)[2]);
294 uGrid->SetPoints(points);
297 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
298 std::vector<int> cellTypes;
299 cellTypes.reserve(mesh->vertices.size() + mesh->lines.size() +
300 mesh->triangles.size() + mesh->tetras.size() +
304 if (mesh->vertices.size() > 0) {
305 for (
auto it = mesh->vertices.begin(); it != mesh->vertices.end(); ++it) {
306 cells->InsertNextCell(1);
307 cells->InsertCellPoint((*it)[0]);
308 cellTypes.push_back(1);
313 if (mesh->lines.size() > 0) {
314 for (
auto it = mesh->lines.begin(); it != mesh->lines.end(); ++it) {
315 cells->InsertNextCell(2);
316 for (
unsigned i = 0; i < 2; ++i) {
317 cells->InsertCellPoint((*it)[i]);
319 cellTypes.push_back(3);
324 if (mesh->triangles.size() > 0) {
325 for (
auto it = mesh->triangles.begin(); it != mesh->triangles.end();
327 cells->InsertNextCell(3);
328 for (
unsigned i = 0; i < 3; ++i) {
329 cells->InsertCellPoint((*it)[i]);
331 cellTypes.push_back(5);
336 if (mesh->tetras.size() > 0) {
337 for (
auto it = mesh->tetras.begin(); it != mesh->tetras.end(); ++it) {
338 cells->InsertNextCell(4);
339 for (
unsigned i = 0; i < 4; ++i) {
340 cells->InsertCellPoint((*it)[i]);
342 cellTypes.push_back(10);
347 if (mesh->hexas.size() > 0) {
348 for (
auto it = mesh->hexas.begin(); it != mesh->hexas.end(); ++it) {
349 cells->InsertNextCell(8);
350 for (
unsigned i = 0; i < 8; ++i) {
351 cells->InsertCellPoint((*it)[i]);
353 cellTypes.push_back(12);
358 uGrid->SetCells(&(cellTypes[0]), cells);
360 addDataFromMesh(mesh->pointData, uGrid->GetPointData());
361 addDataFromMesh(mesh->cellData, uGrid->GetCellData());
362 addMetaDataToVTK(uGrid);
391 vtkSmartPointer<vtkXMLUnstructuredGridWriter> owriter =
392 vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
393 owriter->SetFileName(filename.c_str());
394 owriter->SetInputData(uGrid);
400 void writeVTKLegacy(
const std::string &filename) {
401 if (mesh ==
nullptr) {
402 Logger::getInstance()
403 .addWarning(
"No mesh was passed to VTKWriter.")
408 std::ofstream f(filename.c_str());
410 f <<
"# vtk DataFile Version 2.0" << std::endl;
411 f << ((!mesh->lines.empty()) ? 2 : 3) <<
"D Surface" << std::endl;
412 f <<
"ASCII" << std::endl;
413 f <<
"DATASET UNSTRUCTURED_GRID" << std::endl;
414 f <<
"POINTS " << mesh->nodes.size() <<
" float" << std::endl;
417 for (
unsigned int i = 0; i < mesh->nodes.size(); i++) {
418 for (
int j = 0; j < 3; j++)
419 f <<
static_cast<float>(mesh->nodes[i][j]) <<
" ";
423 const unsigned numberOfCells = mesh->vertices.size() + mesh->lines.size() +
424 mesh->triangles.size() +
425 mesh->tetras.size() + mesh->hexas.size();
426 const unsigned cellDataSize =
427 2 * mesh->vertices.size() + 3 * mesh->lines.size() +
428 4 * mesh->triangles.size() + 5 * mesh->tetras.size() +
429 9 * mesh->hexas.size();
431 f <<
"CELLS " << numberOfCells <<
" " << cellDataSize << std::endl;
434 for (
unsigned int i = 0; i < mesh->vertices.size(); i++) {
435 f << 1 <<
" " << mesh->vertices[i][0] << std::endl;
437 for (
unsigned int i = 0; i < mesh->lines.size(); i++) {
439 for (
int j = 0; j < 2; j++)
440 f << mesh->lines[i][j] <<
" ";
444 for (
unsigned int i = 0; i < mesh->triangles.size(); i++) {
446 for (
int j = 0; j < 3; j++)
447 f << mesh->triangles[i][j] <<
" ";
451 for (
unsigned int i = 0; i < mesh->tetras.size(); i++) {
453 for (
int j = 0; j < 4; j++)
454 f << mesh->tetras[i][j] <<
" ";
458 for (
unsigned int i = 0; i < mesh->hexas.size(); i++) {
460 for (
int j = 0; j < 8; j++)
461 f << mesh->hexas[i][j] <<
" ";
465 f <<
"CELL_TYPES " << numberOfCells << std::endl;
466 for (
unsigned i = 0; i < mesh->vertices.size(); ++i)
469 for (
unsigned i = 0; i < mesh->lines.size(); ++i)
472 for (
unsigned i = 0; i < mesh->triangles.size(); ++i)
475 for (
unsigned i = 0; i < mesh->tetras.size(); ++i)
476 f << 10 << std::endl;
478 for (
unsigned i = 0; i < mesh->hexas.size(); ++i)
479 f << 12 << std::endl;
482 if (mesh->pointData.getScalarDataSize() ||
483 mesh->pointData.getVectorDataSize()) {
484 Logger::getInstance()
485 .addWarning(
"Point data output not supported for legacy VTK output. "
486 "Point data is ignored.")
491 if (mesh->cellData.getScalarDataSize()) {
492 f <<
"CELL_DATA " << mesh->cellData.getScalarData(0)->size() << std::endl;
493 for (
unsigned i = 0; i < mesh->cellData.getScalarDataSize(); ++i) {
494 auto scalars = *(mesh->cellData.getScalarData(i));
495 f <<
"SCALARS " << mesh->cellData.getScalarDataLabel(i) <<
" float"
497 f <<
"LOOKUP_TABLE default" << std::endl;
498 for (
unsigned j = 0; j < scalars.size(); ++j) {
499 f << ((std::abs(scalars[j]) < 1e-6) ? 0.0 : scalars[j]) << std::endl;
505 if (mesh->cellData.getVectorDataSize()) {
506 if (!mesh->cellData.getScalarDataSize())
507 f <<
"CELL_DATA " << mesh->cellData.getVectorData(0)->size()
509 for (
unsigned i = 0; i < mesh->cellData.getVectorDataSize(); ++i) {
510 auto vectors = *(mesh->cellData.getVectorData(i));
511 f <<
"VECTORS " << mesh->cellData.getVectorDataLabel(i) <<
" float"
513 for (
unsigned j = 0; j < vectors.size(); ++j) {
514 for (
unsigned k = 0; k < 3; ++k) {
515 f << vectors[j][k] <<
" ";