I'm trying to convert from data structure about mesh I made by myself to vtu format file. Thanks to the answer of the question I still made, I was able to create vtu format files.
However, all points belonging to multiple cells were output to the file as many as the number of cells. (In output.vtu, NumberOfPoints="10648" NumberOfCells="1331". 1331 * 8 = 10648) And if I tried to see that file in paraview I could not open it.
I do not know how to write vtkUnstructuredGrid with sharing coordinates . I'd be grateful for any hints.
This is the code I wrote.
MyMesh
contains cell and vertex information.
bool writeVtu(MyMesh *mesh, const char *path)
{
// create the append filter
vtkSmartPointer<vtkAppendFilter> append =
vtkSmartPointer<vtkAppendFilter>::New();
// add each data set
for(int i = 0; i < num_cell; i++)
{
append->AddInputData(addCell(mesh->cell(i)));
}
append->Update();
// write the result
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(path);
writer->SetInputData(append->GetOutput());
writer->Write();
return true;
}
vtkSmartPointer<vtkUnstructuredGrid>
addCell(MyCell* cell)
{
int numberOfVertices = cell->numVertices();
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
for(int i = 0; i < numberOfVertices; i++){
points->InsertNextPoint(cell->getVertex(i)->getxyz());
}
vtkSmartPointer<vtkIdList> idList = vtkIdList::New();
idList->SetNumberOfIds(numberOfVertices);
for (vtkIdType i = 0; i < numberOfVertices; i++)
{
idList->SetId(i, i);
}
vtkSmartPointer<vtkUnstructuredGrid> ug =
vtkSmartPointer<vtkUnstructuredGrid>::New();
ug->InsertNextCell(
vtkCellType(cell->vtkType()) , idList);
ug->SetPoints(points);
return ug;
}
Apriori, assuming MyMesh
provide global identifiers for the vertices, you could do the following:
bool writeVtu(MyMesh *mesh, const char *path)
{
// create the unstructured grid
vtkSmartPointer<vtkUnstructuredGrid> ug =
vtkSmartPointer<vtkUnstructuredGrid>::New();
// create the shared points structure
vtkSmartPointer<vtkPoints> pts =
vtkSmartPointer<vtkPoints>::New();
pts->SetNumberOfPoints(num_points);
// add each cell
for(int i = 0; i < num_cell; i++)
{
addCell(mesh->cell(i), ug, pts);
}
// add the points
ug->SetPoints(pts);
// write the result
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(path);
writer->SetInputData(ug);
writer->Write();
return true;
}
void addCell(MyCell *cell,
vtkSmartPointer<vtkUnstructuredGrid> ug,
vtkSmartPointer<vtkPoints> points)
{
int numberOfVertices = cell->numVertices();
vtkSmartPointer<vtkIdList> idList = vtkIdList::New();
idList->SetNumberOfIds(numberOfVertices);
for(int i = 0; i < numberOfVertices; i++){
int globalId = cell->getVertex(i)->getId();
idList->SetId(i, globalId);
points->SetPoint(globalId, cell->getVertex(i)->getxyz());
}
ug->InsertNextCell(
vtkCellType(cell->vtkType()) , idList);
}
This version of addCell
adds the topology and the geometry at the same time and the structure managing the points is allocated accordingly at the beginning.
Here, I did not use vtkAppendFilter
because I think that one vtkUnstructuredGrid
can do the same job (based on the original version of the code).
Please note that this code is untested so be aware that it can contain errors. A call to ug->Allocate(num_cells)
before inserting the cells may be necessary.
EDIT: I modified the second argument of the function SetId()
to globalId
as suggested by R. Y