217 Star 1K Fork 245

GVPpyminer / pyminer

 / 详情

【三维绘图】对vtk python接口做一个封装实现三维绘图

待办的
需求 成员
创建于  
2020-09-03 23:02

三维绘图的选择 : 新版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

附件
熊二 2020-09-03 23:01

评论 (3)

熊二 创建了需求
熊二 关联仓库设置为py2cn/pyminer
熊二 修改了描述
熊二 优先级设置为主要
westat 添加了
 
奇思妙想
标签
westat 添加了
 
讨论
标签
展开全部操作日志

我尝试了一下,vtk还是比较好安装的。对于pyminer,可以考虑集成在程序内部。

但这个包大约有150M,大小比较感人;在线安装的话,pip经常会由于依赖问题把解释器的site_packages彻底弄崩。所以我建议推出一个几合一的包,集成vtk\pyopengl等常用环境,放在插件里面,由python解释器调用。这样即使安装失利,也不会影响到程序的安全性。

如果我们到时候有了速度比较快的服务器,那么或许可以考虑挂在自己的源上面,作为一种插件进行发布。这样安装起来不会像pip那样崩环境。

下图是我在当前的环境中调用外部第三方包运行的vtk。但是,集成mayavi,的确有点难度。

输入图片说明

hzy15610046011 移除了
 
奇思妙想
标签
hzy15610046011 移除了
 
讨论
标签
hzy15610046011 添加了
 
enhancement
标签
hzy15610046011 添加了
 
feature
标签
hzy15610046011 修改了描述
hzy15610046011 修改了描述

pyqt5 + vtk(python3+qt5)

代码

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_())

结果

输入图片说明

依赖

  • vtk9.0.1
  • Qt5.15.0
  • python3.8

注意: 源码编译VTK时,在cmake中启用如下选项

  • VTK_GROUP_ENABLE_Qt=Yes
  • VTK_WRAP_PYTHON=Yes
  • VTK_PYTHON_VERSION=3

vtk集成进pyminer不会存在很大问题的。

vtk + numpy

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,是可行的。难点在于各个模块(插件)间数据交互的标准。

westat 关联项目设置为PyMiner
westat 移除了
 
enhancement
标签
westat 移除了
 
feature
标签
westat 添加了
 
PyQt
标签
熊二 修改了标题
熊二 修改了描述

可以使用pyvista,这个库已经封装vtk

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(4)
Python
1
https://gitee.com/py2cn/pyminer.git
git@gitee.com:py2cn/pyminer.git
py2cn
pyminer
pyminer

搜索帮助