三维绘图的选择 : 新版Qt中有rhl,可以基于现代图形API绘制,vulkan,metal。
三维绘图的难点 : 非真实感绘制,对渲染算法要求不高,难点在于提供一个通用的绘制模块
三维绘图的流程 : 开发三维绘图的插件包集成到PyMiner中
三维绘图的原理及资源消耗:
这种曲线或者曲面的渲染,只要做了基本的优化,消耗的资源是非常少的,比如GPU资源要尽可能少的更新,调用DrawCall的次数尽可能少(尽量把绘制放到一个批次里)等。
三维绘图的pyqt的模块选择 : QtCharts 或 QtDataVisualization 或 VTK
模块之间的取舍(优缺点):
1、VTK开发难度相对另外两者来说难度更大,VTK更专业,也是一个比较庞大的类库,不但是绘图(2D和3D),还包含很多几何算法,比如网格简化,细分,曲率计算,求交等等,从长远考虑,VTK通用性更强些,VTK C++版就内置和QT的集成
2、QtChart是二维的曲线,条形图等,QtDataVisualization是三维的
三维绘图的探索 :
对vtk python接口做一个封装实现三维绘图
方案:
VTK本身对于2D和3D的chart也都是有模块的,只需要将数据适配好就行了,数据适配:就是基础的数据,我们得有规范,打个比方就是,matlab里,很多第三方的模块,绘图或者模拟等,都是接受它的矩阵类型,我们也得有这些基础的类型,矩阵,向量,张量等等。其它的插件应该都是接受这些类型,因为所以这些图形或者几何的库,都会有自己的矩阵或者向量类型,我们在使用它们开发插件的时候,接收的都是我们自己的类型,但调用这些库时都要转化成他们需要的类型。这个数据类型的转化工作,对于其他模块的人必须是透明的。numpy应该是可以的,对于绘图或者几何处理来说,一般都是要求连续内存的格式,类似于C语言的数组或者c++的vector。可以用现成的数据类型比如numpy,但得定下规范。
重点: 但是基础数据格式,不仅仅是绘图,其它的各个模块都要尽量统一,减少转换。
补充 : numpy和scipy和mpl基本可以替代matlab的基础。
绘图这块,各有各的优势,matlab交互很到位,但属性修改器不多,mpl的交互太渣,但各种属性修改都有涉及,甚至比matlab的多很多。停留在数组层面操作就足够了。
2020年9月17日补充:
vtk本就是开源的,可以在vtk基础上封装一个轻量级的三维数据可视化模块,数据格式跟pyminer主程序一致。但是vtk进行二维图像算法的效率较低,可以不用。
这个库满足数据渲染,一般交互,数据分割,创建模型,修改属性等,体积会很小。作者@暗里着迷月儿的光线投射算法是自己实现的,用在arm上。vtk自身就实现了光线投射算法。开源项目用于科学计算分析的话,建议直接封装vtk,满足pyminer
我尝试了一下,vtk还是比较好安装的。对于pyminer,可以考虑集成在程序内部。
但这个包大约有150M,大小比较感人;在线安装的话,pip经常会由于依赖问题把解释器的site_packages彻底弄崩。所以我建议推出一个几合一的包,集成vtk\pyopengl等常用环境,放在插件里面,由python解释器调用。这样即使安装失利,也不会影响到程序的安全性。
如果我们到时候有了速度比较快的服务器,那么或许可以考虑挂在自己的源上面,作为一种插件进行发布。这样安装起来不会像pip那样崩环境。
下图是我在当前的环境中调用外部第三方包运行的vtk。但是,集成mayavi,的确有点难度。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
import sys
import vtk
from PyQt5 import QtCore, QtGui
from PyQt5 import Qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
class MainWindow(Qt.QMainWindow):
def __init__(self, parent = None):
Qt.QMainWindow.__init__(self, parent)
self.frame = Qt.QFrame()
self.vl = Qt.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 source
source = vtk.vtkSphereSource()
source.SetCenter(0, 0, 0)
source.SetRadius(5.0)
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
self.ren.AddActor(actor)
self.ren.ResetCamera()
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
self.iren.Initialize()
self.iren.Start()
if __name__ == "__main__":
app = Qt.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
注意: 源码编译VTK时,在cmake中启用如下选项
vtk集成进pyminer不会存在很大问题的。
import sys
import vtk
from PyQt5 import QtCore, QtGui
from PyQt5 import Qt
from vtk.numpy_interface import dataset_adapter as dsa
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import numpy as np
class MainWindow(Qt.QMainWindow):
def __init__(self, parent = None):
Qt.QMainWindow.__init__(self, parent)
self.frame = Qt.QFrame()
self.vl = Qt.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 source
source = vtk.vtkSphereSource()
source.SetCenter(0, 0, 0)
source.SetRadius(5.0)
source.Update()
# use numpy interface
old = source.GetOutput()
old = dsa.WrapDataObject(old)
points = old.GetPoints()
cells = old.GetPolygons()
print(points)
print(cells)
types = np.full(int(len(cells)/4),vtk.VTK_TRIANGLE,dtype=np.uint8)
print(types)
locs = np.arange(0,len(cells),4,dtype=np.int32)
print(locs)
newSource = vtk.vtkUnstructuredGrid()
newSource = dsa.WrapDataObject(newSource)
newSource.SetPoints(points)
newSource.SetCells(types,locs,cells)
# Create a mapper
mapper = vtk.vtkDataSetMapper()
# mapper.SetInputConnection(source.GetOutputPort())
mapper.SetInputData(newSource.VTKObject)
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
self.ren.AddActor(actor)
self.ren.ResetCamera()
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
self.iren.Initialize()
self.iren.Start()
if __name__ == "__main__":
app = Qt.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
总得来说, python3+pyqt+vtk+numpy,是可行的。难点在于各个模块(插件)间数据交互的标准。
可以使用pyvista,这个库已经封装vtk
登录 后才可以发表评论