Search code examples
vtk

How to write vtkUnstructuredGrid with sharing coordinates


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;
}

Solution

  • 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