Converting vtkUnstructuredGrid to vtkPolyData

I have a vtkUnstructuredGrid that is a contiguous mass of connected vtkHexahedrons (it is an appended grouping of vtkUnstructuredGrid). I want to use some algorithms that only work with vtkPolyData (namely I want to delete some cells where a variable is small). The data is very large, and I want to make sure that I am not deep copying.

Right now, this is how the script looks:

# data is a vtkUnstructuredGrid
# data.GetPointData().GetNumberOfArrays() --> 9
# data.GetNumberOfPoints() --> more than 12 million
# I'm not sure if these 'Set' functions make deep or shallow copies ...
pd = vtk.vtkPolyData()
pd.SetPoints(data.GetPoints())
pd.SetPolys(data.GetCells())
for a_idx in range(data.GetPointData().GetNumberOfArrays()):
    pd.GetFieldData().AddArray(data.GetPointData().GetArray(a_idx))

It does occur to me that I can’t add vtkHexahedrons to a vtkPolyData … ultimately I want the faces of the hexahedrons in there … but the above code for sure will not work.

If you only want the external surface of your mesh, you may want to look at the vtkGeometryFilter.
If you want to all the internal faces, do you need them to stay connected ? do you need them to stay quads ?

Thanks - I hadn’t heard of vtkGeometryFilter, I actually do need the insides of the object - I mostly wanted to convert the thing to vtkPolyData so that I could run vtkCleanPolyData on it. I am beginning to realize that the real answer to my question is “it depends.” In my, very strange, circumstance the code that generated what I needed was:

    # FIXME: hardcoded: Temperature is index 7
    logging.debug("generating vtkCellArray of unique faces")
    CELL_NODE_COUNT = data.GetCell(0).GetNumberOfPoints()
    FACE_NODE_COUNT = data.GetCell(0).GetFace(0).GetNumberOfPoints()
    temp_array = pd.GetPointData().GetAbstractArray(7)
    unique_quads = set()
    ca = vtk.vtkCellArray()

    for c_idx in range(data.GetNumberOfCells()):
        # Skip those cells for which the average nodal temperature is <= T_LOWER_LIMIT
        cell = data.GetCell(c_idx)
        cell_node_temps = [temp_array.GetTuple1(cell.GetPointId(n)) for n in range(CELL_NODE_COUNT)]
        if np.mean(cell_node_temps) <= T_LOWER_LIMIT:
            continue

        # Break cell into faces, and only add unique faces.
        for f_idx in range(data.GetCell(0).GetNumberOfFaces()):
            face = data.GetCell(c_idx).GetFace(f_idx)
            face_ids = [face.GetPointId(x) for x in range(FACE_NODE_COUNT)]
            sorted_ids = tuple(sorted(face_ids))
            reversed_ids = tuple(reversed(sorted(face_ids)))
            sorted_ids = min(sorted_ids, reversed_ids)
            if sorted_ids not in unique_quads:
                unique_quads.add(sorted_ids)
                ca.InsertNextCell(FACE_NODE_COUNT, face_ids)

    pd.SetPolys(ca)

    logging.debug("cleaning final vtkPolyData")
    cpd = vtk.vtkCleanPolyData()
    cpd.SetInputData(pd)
    cpd.Update()