# Problem displaying 2 surfaces together in one window, in Python way

**URL:** <https://discourse.slicer.org/t/problem-displaying-2-surfaces-together-in-one-window-in-python-way/34159>\
**Category:** VMTK\
**Tags:** vmtk\
**Created:** [February 5, 2024, 10:26pm UTC](https://discourse.slicer.org/t/problem-displaying-2-surfaces-together-in-one-window-in-python-way/34159 "2024-02-05T22:26:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![guozhi0302](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/guozhi0302/32/69245_2.png) [@guozhi0302](https://discourse.slicer.org/u/guozhi0302)\
**Post date:** [February 5, 2024, 10:26pm UTC](https://discourse.slicer.org/t/problem-displaying-2-surfaces-together-in-one-window-in-python-way/34159/1 "2024-02-05T22:26:31Z")

</div>

The official tutorial [Computing Centerlines](http://www.vmtk.org/tutorials/Centerlines.html) has demonstrated displaying multiple surfaces (or centerlines) in one window with Pype commands.

```auto
vmtksurfacereader -ifile foo.vtp --pipe vmtkcenterlines --pipe vmtkrenderer --pipe vmtksurfaceviewer -opacity 0.25 --pipe vmtksurfaceviewer -i @vmtkcenterlines.o -array MaximumInscribedSphereRadius

```

However, the way the piping works has confused me. It seems that the last vmtkSurfaceViewer not only receive a surface (foo.vtp) from its previous vmtkSurfaceViewer, but also the centerline as a second input.  
Is there any way to do the same thing in Python’s object-oriented manner?

---

<div class="post-metadata">

**Author:** ![guozhi0302](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/guozhi0302/32/69245_2.png) [@guozhi0302](https://discourse.slicer.org/u/guozhi0302)\
**Post date:** [February 7, 2024, 1:53pm UTC](https://discourse.slicer.org/t/problem-displaying-2-surfaces-together-in-one-window-in-python-way/34159/3 "2024-02-07T13:53:20Z")

</div>

To answer my own question,  
After reading vmtkSurfaceViewer()'s source code, I still feel its piping too complicated to understand.  
However, I use VTK’s functions instead to combine polydata (surfaces and centerlines) first. The combined data is then fed into vmtkRenderer(). VTK’s own Renderer is also available, but I prefer VMTK’s.  
The following is my code. Part of it referenced [this post](https://discourse.vtk.org/t/how-to-change-the-colors-of-objects-in-vtk-when-using-vtkappendpolydata/2431). It allows setting color and opacity for each polydata. Readers are vmtkSurfaceReader()s.

```auto
class PolydataViewer():
    def __init__ (self):
        self.appendFilter = vtk.vtkAppendPolyData()

    def add_polydata(self, polydata, color=[255, 255, 255], opacity=1):
        colors = vtk.vtkUnsignedCharArray()
        colors.SetNumberOfComponents(4)
        colors.SetName("DisplayColor")
        colors.SetNumberOfTuples(polydata.GetNumberOfCells())
        for c in range(polydata.GetNumberOfCells()):
            colors.SetTuple(c, (*color, int(opacity * 255)))
        polydata.GetCellData().AddArray(colors)
        self.appendFilter.AddInputData(polydata)

    def show(self, background=None):
        self.appendFilter.Update()
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(self.appendFilter.GetOutputPort())
        mapper.SetScalarModeToUseCellFieldData()
        mapper.SelectColorArray('DisplayColor')
        actor = vtk.vtkActor()
        actor.SetMapper(mapper)

        renderer = vmtk.vmtkrenderer.vmtkRenderer()
        renderer.Initialize()
        if background is not None:
            renderer.Renderer.SetBackground(np.array(background) / 255)
        renderer.Renderer.AddActor(actor)
        renderer.Render()
        renderer.Deallocate()

viewer = PolydataViewer()
viewer.add_polydata(reader1.Surface, color=[255, 0, 0], opacity=0.3)
viewer.add_polydata(reader2.Surface, color=[255, 255, 0])
viewer.show()

```
