This post provides a detailed guide on setting up the Visualization Toolkit (VTK) environment within PyQt5. It covers the introduction and installation of VTK, offering methods for installation via Anaconda and wheel files. The article includes simple VTK examples, such as drawing a cube and integrating VTK rendering windows in PyQt5 applications. Additionally, it demonstrates how to read STL files using VTK in PyQt5 and outlines the 3D file formats supported by VTK, making it a comprehensive resource for developers looking to leverage VTK's capabilities in their projects.
Introduction and Installation of VTK
Introduction to VTK
VTK (Visualization Toolkit) is an open-source software system primarily used for 3D computer graphics, image processing, and visualization. VTK is designed and implemented based on object-oriented principles. Its core is built with C++, containing approximately 250,000 lines of code and over 2,000 classes. It also includes several interface layers, allowing it to be freely used through various programming languages including Java, Tcl/Tk, and Python.
VTK is an open-source, freely available software system used by thousands of researchers and developers worldwide for 3D computer graphics, image processing, and visualization. VTK includes a C++ class library and multiple translation interface layers including Tcl/Tk, Java, and Python. The Visualization Toolkit is a supporting environment for constructing and running visualization applications. It is developed using object-oriented design methods based on the OpenGL 3D library, encapsulating common details and algorithms encountered in visualization development. For example, the Visualization Toolkit encapsulates the commonly used MarchingCubes algorithm for surface reconstruction as a class, allowing developers to directly use the provided vtkMarchingCubes class instead of rewriting the MarchingCubes algorithm code when performing surface reconstruction of 3D regular grid data. The Visualization Toolkit serves as a powerful visualization development tool providing direct technical support for researchers engaged in visualization application development.
Installing VTK in Python Environment
Method 1: Installation via Anaconda using conda install
Note that different Python versions correspond to different commands.
For Python 3
install -n envA -c menpo vtk=7 python=3
or if you want to be more specific:
conda install -n envB -c menpo vtk=7 python=3.5
For Python 3.6:
conda install -c clinicalgraphics vtk=7.1.0
Version numbers can be omitted in all the above commands.
Method 2: Installation via Wheel Files
Since VTK packages are not available in some regional package mirrors, direct installation through conda can be very slow. It is recommended to download the wheel (.whl) file and install it using pip.
For example, on a Windows 10 64-bit system with Python 3.7, you would download: VTK‑8.1.2‑cp37‑cp37m‑win32.whl
After downloading, navigate to the download directory and open cmd, Windows PowerShell, or Git Bash. Then run the command: pip install VTK-7.1.1-cp36-cp36m-win_amd64.whl to complete the installation.
Once installed, you can import the vtk package in your code.
#!/usr/bin/env python# This is (almost) a direct C++ to Python transliteration of# <VTK-root>/Examples/DataManipulation/Cxx/Cube.cxx from the VTK# source distribution, which "shows how to manually create vtkPolyData"## A convenience function, mkVtkIdList(), has been added and one if/else# so the example also works in version 6 or later.## Lines like `obj->Delete()` have been transliterated as `del obj` to,# preserve the resemblance to the original C++ example, although I# doubt this achieves anything beyond what Python's garbage collection# would do anyway.importvtk# Makes a vtkIdList from a Python iterable. I'm kinda surprised that# this is necessary, since I assumed that this kind of thing would# have been built into the wrapper and happen transparently, but it# seems not.defmkVtkIdList(it):vil=vtk.vtkIdList()foriinit:vil.InsertNextId(int(i))returnvil# 绘制通用方法defmyShow(cube):# Now we'll look at it.cubeMapper=vtk.vtkPolyDataMapper()ifvtk.VTK_MAJOR_VERSION<=5:cubeMapper.SetInput(cube)else:cubeMapper.SetInputData(cube)cubeMapper.SetScalarRange(0,7)cubeActor=vtk.vtkActor()cubeActor.SetMapper(cubeMapper)# The usual rendering stuff.camera=vtk.vtkCamera()camera.SetPosition(1,1,1)camera.SetFocalPoint(0,0,0)renderer=vtk.vtkRenderer()renWin=vtk.vtkRenderWindow()renWin.AddRenderer(renderer)iren=vtk.vtkRenderWindowInteractor()iren.SetRenderWindow(renWin)renderer.AddActor(cubeActor)renderer.SetActiveCamera(camera)renderer.ResetCamera()renderer.SetBackground(0,0,0)renderer.SetBackground(1.0,1.0,1.0)renderer.SetBackground2(0.1,0.2,0.4)renderer.SetGradientBackground(1)renWin.SetSize(300,300)# interact with datarenWin.Render()iren.Start()delcubeMapperdelcubeActordelcameradelrendererdelrenWindelirendefmain():# x = array of 8 3-tuples of float representing the vertices of a cube:# 8个三维值代表长方体的8个顶点x=[(0.0,0.0,0.0),(1.0,0.0,0.0),(1.0,1.0,0.0),(0.0,1.0,0.0),(0.0,0.0,1.0),(1.0,0.0,1.0),(1.0,1.0,1.0),(0.0,1.0,1.0)]# pts = array of 6 4-tuples of vtkIdType (int) representing the faces# of the cube in terms of the above vertices# 点的编号0-7,每个面由4个点组成pts=[(0,1,2,3),(4,5,6,7),(0,1,5,4),(1,2,6,5),(2,3,7,6),(3,0,4,7)]# We'll create the building blocks of polydata including data attributes.cube=vtk.vtkPolyData()points=vtk.vtkPoints()polys=vtk.vtkCellArray()scalars=vtk.vtkFloatArray()# Load the point, cell, and data attributes.foriinrange(8):points.InsertPoint(i,x[i])foriinrange(6):polys.InsertNextCell(mkVtkIdList(pts[i]))foriinrange(8):scalars.InsertTuple1(i,i)# We now assign the pieces to the vtkPolyData.cube.SetPoints(points)delpointscube.SetPolys(polys)delpolyscube.GetPointData().SetScalars(scalars)delscalarsmyShow(cube)# Clean updelcubemain()
The execution result is shown in the following image:
fromPyQt5.QtWidgetsimportQApplication,QMainWindowimportsysimportvtkfromPyQt5importQtCore,QtGui,QtWidgetsfromvtk.qt.QVTKRenderWindowInteractorimportQVTKRenderWindowInteractorclassmyMainWindow(QtWidgets.QMainWindow):def__init__(self,parent=None):QtWidgets.QMainWindow.__init__(self,parent)self.frame=QtWidgets.QFrame()self.vl=QtWidgets.QVBoxLayout()self.vtkWidget=QVTKRenderWindowInteractor(self.frame)self.vl.addWidget(self.vtkWidget)self.ren=vtk.vtkRenderer()self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)self.iren=self.vtkWidget.GetRenderWindow().GetInteractor()# Create sourcesource=vtk.vtkConeSource()source.SetCenter(0,0,0)source.SetRadius(0.1)source1=vtk.vtkSphereSource()source1.SetCenter(0,0,0)source1.SetRadius(0.3)# Create a mappermapper=vtk.vtkPolyDataMapper()mapper.SetInputConnection(source.GetOutputPort())mapper1=vtk.vtkPolyDataMapper()mapper1.SetInputConnection(source1.GetOutputPort())# Create an actoractor=vtk.vtkActor()actor.SetMapper(mapper)actor1=vtk.vtkActor()actor1.SetMapper(mapper1)self.ren.AddActor(actor)self.ren.AddActor(actor1)self.ren.ResetCamera()self.frame.setLayout(self.vl)self.setCentralWidget(self.frame)self.show()self.iren.Initialize()if__name__=="__main__":app=QApplication(sys.argv)window=myMainWindow()sys.exit(app.exec_())
# 部分代码,在PyQt主程序中以addWidget形式嵌入到主窗口中# 添加VTK显示窗读取STL文件===============================================self.vtkWidget=QVTKRenderWindowInteractor(self.centralwidget)# 提供平台独立的响应鼠标、键盘和时钟事件的交互机制self.verticalLayout_3.addWidget(self.vtkWidget)self.ren=vtk.vtkRenderer()# 负责管理场景的渲染过程self.ren.SetBackground(1.0,1.0,1.0)# 设置页面底部颜色值self.ren.SetBackground2(0.1,0.2,0.4)# 设置页面顶部颜色值self.ren.SetGradientBackground(1)# 开启渐变色背景设置self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)self.iren=self.vtkWidget.GetRenderWindow().GetInteractor()# 交互器样式的一种,该样式下,用户是通过控制相机对物体作旋转、放大、缩小等操作style=vtk.vtkInteractorStyleTrackballCamera()self.iren.SetInteractorStyle(style)# Read from STL filestlreader=vtk.vtkSTLReader()stlreader.SetFileName("test.stl")# Read from OBJ file# objReader = vtk.vtkOBJReader()# objReader.SetFileName("test.obj")# Create a mappermapper=vtk.vtkPolyDataMapper()# 渲染多边形几何数据mapper.SetInputConnection(stlreader.GetOutputPort())# VTK可视化管线的输入数据接口 ,对应的可视化管线输出数据的接口为GetOutputPort();# mapper.SetInputConnection(objReader.GetOutputPort())# Create an actoractor=vtk.vtkActor()actor.SetMapper(mapper)# 设置生成几何图元的Mapper。即连接一个Actor到可视化管线的末端(可视化管线的末端就是Mapper)。self.ren.AddActor(actor)self.ren.ResetCamera()self.centralwidget.setLayout(self.verticalLayout_3)self.setCentralWidget(self.centralwidget)self.vtkWidget.show()self.iren.Initialize()
Execution results:
3D File Formats Supported by VTK
VTK supports importing/exporting and reading/writing various 3D file formats. For more information, you can refer to
What 3D file formats can VTK import and export?
The following table outlines the file formats that VTK can handle. Importer and Exporter classes are used to transfer complete scene information to and from VTK, while Reader and Writer classes handle geometric data only.