Rendering a lattice graph

I would like to display a 3D lattice DAG, where every vertex has associated integer (x,y,z) coordinates, and the edges are the edges of the corresponding cubic lattice. I can build the graph with vtkMutableDirectedGraph and vtkTree, but I can’t figure out how to assign the coordinates and which mapper to use (I want vertices as spheres and edges as tubes or arrows).

There’s vtkGraph.SetPoints, but are those associated with the vertices? There’s vertex data which I could use to store the coordinates, but how can I set the data as I add each vertex (and not as a whole array for all vertices at one shot), and how I can use this in a mapper?

For instance, using Python, I can create this simple vtkTree:

graph = vtk.vtkMutableDirectedGraph()
v0 = graph.AddVertex()
v1a = graph.AddVertex()
v1b = graph.AddVertex()
v1c = graph.AddVertex()
graph.AddEdge(v0, v1a)
graph.AddEdge(v0, v1b)
graph.AddEdge(v0, v1c)
coord = vtk.vtkIntArray()
coord.SetName('coord')
coord.SetNumberOfComponents(3)
coord.InsertNextTuple([0,0,0])
coord.InsertNextTuple([1,0,0])
coord.InsertNextTuple([0,1,0])
coord.InsertNextTuple([0,0,1])
graph.GetVertexData().AddArray(coord)
tree = vtk.vtkTree()
tree.CheckedShallowCopy(graph)

How can I now display it, as I said, with spheres and tubes? (And ideally adding the coordinates in the AddVertex calls)

I suggest taking a look at vtkMolecule and vtkMoleculeMapper for your use-case.

vtkMolecule is an undirected graph (with bells and whistles I don’t need), I want a directed graph.

I found what I needed in vtkGraphToPolyData. Also it seems the Points is effectively a property associated to the vertices that is used by vtkGraphToPolyData directly, so no need to use a separate VertexData. The following is a working code for what I wanted:

#! /usr/bin/env python3

import vtk

graph = vtk.vtkMutableDirectedGraph()
v0 = graph.AddVertex()
v1a = graph.AddVertex()
v1b = graph.AddVertex()
v1c = graph.AddVertex()
graph.AddEdge(v0, v1a)
graph.AddEdge(v0, v1b)
graph.AddEdge(v0, v1c)
coord = vtk.vtkPoints()
coord.InsertNextPoint([0,0,0])
coord.InsertNextPoint([1,0,0])
coord.InsertNextPoint([0,1,0])
coord.InsertNextPoint([0,0,1])
graph.SetPoints(coord)
tree = vtk.vtkTree()
tree.CheckedShallowCopy(graph)

# Convert to PolyData
graphToPolyData = vtk.vtkGraphToPolyData()
graphToPolyData.SetInputData(graph)
graphToPolyData.Update()

# Tubes filter for the edges
tubes = vtk.vtkTubeFilter()
tubes.SetInputConnection(graphToPolyData.GetOutputPort())
tubes.SetRadius(0.05)
tubes.SetNumberOfSides(6)

# Spheres filter for the vertices
ball = vtk.vtkSphereSource()
ball.SetRadius(0.1)
ball.SetThetaResolution(12)
ball.SetPhiResolution(12)
balls = vtk.vtkGlyph3D()
balls.SetSourceConnection(ball.GetOutputPort())
balls.SetInputConnection(graphToPolyData.GetOutputPort())

# Create mappers and actors
ballsMapper = vtk.vtkPolyDataMapper()
ballsMapper.SetInputConnection(balls.GetOutputPort())
tubesMapper = vtk.vtkPolyDataMapper()
tubesMapper.SetInputConnection(tubes.GetOutputPort())

ballsActor = vtk.vtkActor()
ballsActor.SetMapper(ballsMapper)
tubesActor = vtk.vtkActor()
tubesActor.SetMapper(tubesMapper)

# Create a renderer, render window, and interactor
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())

# Add the actors to the scene
renderer.AddActor(ballsActor)
renderer.AddActor(tubesActor)

# Render and interact
renderWindow.SetWindowName('Graph')
renderWindow.Render()
renderWindowInteractor.Start()