Search code examples
c++vtkparaview

How to set multiple cell array for same vtk vtkUnstructuredGrid?


I use c++ vtk to visualize fields in paraview via unstructuredGrid. If i use SetVectors twice, vtk write only last vector field.

How to write more than one data array in .vtu file ?

Here is minimal reproducible example. In this case, I'm wrighting 4 points and one quad shell with two cell arrays. Paraview shows that out.vtu file contain only one shear stress field array.

   //VTK heaaders 
#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkDataSetMapper.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTetra.h>
#include <vtkQuad.h>
#include <vtkTriangle.h>

#include <vtkUnstructuredGrid.h>
#include <vtkXMLUnstructuredGridReader.h>
#include <vtkXMLUnstructuredGridWriter.h>
#include <vtkCellData.h>
#include <vtkDoubleArray.h>




int main () {

    vtkNew<vtkPoints> points;
    // Make 4 points
    points->InsertNextPoint(0., 0., 0.);
    points->InsertNextPoint(1., 0., 0.);
    points->InsertNextPoint(1., 1, 0);
    points->InsertNextPoint(0., 1., 0.);
    vtkNew<vtkCellArray> cellArray;
    vtkNew<vtkQuad> quad;
    // make single quad
    quad->GetPointIds()->SetId(0, 0);
    quad->GetPointIds()->SetId(1, 1);
    quad->GetPointIds()->SetId(2, 2);
    quad->GetPointIds()->SetId(3, 3);
    cellArray->InsertNextCell(quad);

    
    vtkNew<vtkUnstructuredGrid> unstructuredGrid;
    unstructuredGrid->SetPoints(points);
    unstructuredGrid->SetCells(VTK_QUAD, cellArray);
    // Data Arrays
    vtkSmartPointer<vtkDoubleArray> Sigma = vtkSmartPointer<vtkDoubleArray>::New();
    Sigma->SetName("Normal Stress");
    Sigma->SetNumberOfComponents(3);
    vtkSmartPointer<vtkDoubleArray>  Tau = vtkSmartPointer<vtkDoubleArray>::New();
    Tau->SetName("Shear Stress ");
    Tau->SetNumberOfComponents(3);
    //  insert values to arrays
    Sigma->InsertNextValue(100.);
    Sigma->InsertNextValue(100.);
    Sigma->InsertNextValue(100.);
    Tau->InsertNextValue(100.);
    Tau->InsertNextValue(100.);
    Tau->InsertNextValue(100.);
    // insert data array to grid
    unstructuredGrid->GetCellData()->SetVectors(Sigma);
    // Tau will overwright sigma field 
    //  How to fix it
    unstructuredGrid->GetCellData()->SetVectors(Tau);
    
    vtkNew<vtkXMLUnstructuredGridWriter> writer;
    writer->SetFileName("out.vtu");
    writer->SetInputData(unstructuredGrid);
    writer->Write();
    return 0;
}


Solution

  • Don't call vtkCellData::SetVectors() to add data arrays. Call vtkCellData()::AddArray() instead. The same holds true if you are using vtkPointData::SetVectors() for setting point data arrays. SetVectors() adds the data array you pass to it, but it also entirely removes the data array that was previously added to your vtkCellData through your first SetVectors() call, which is indeed surprising behavior.

    Explanation: vtkCellData::SetVectors() adds the data array to the cell data and designates it as the vectors in a dataset, which is information VTK filters used to use to decide which data arrays to process. This is an antiquated way of doing things, and really isn't needed anymore. Instead, there is other API at the filter level one uses to tell filters which data arrays to process.