一、基于Qt Data Visualization Examples中的Surface Example模块(未完成)
Surface Example - Qt for Python 给出了一种通过Q3DSurface绘制三维空间曲面的例子,包含以下几个功能:
这个例子与CFD软件中网格显示十分相似,在此基础上也许可以实现对.msh文件、.su2文件的显示。
首先,在main.py中,我们创建一个QApplication,实例化Q3DSurface,并为它创建一个窗口容器:
app = QApplication([]) graph = Q3DSurface() container = QWidget.createWindowContainer(graph)
调用createWindowContainer是必需的,因为所有的数据可视化图形类(Q3DBars, Q3DScatter和Q3DSurface)继承QWindow。任何继承QWindow的类都不能以任何其他方式作为小部件使用。
然后我们将创建水平和垂直布局,将图表添加到容器中,将垂直布局添加到水平布局:
widget = QWidget() hLayout = QHBoxLayout(widget) vLayout = QVBoxLayout() hLayout.addWidget(container, 1) hLayout.addLayout(vLayout) vLayout.setAlignment(Qt.AlignTop)
main.py中的其余代码是为Q3DSurface中的特性创建控件小部件。我们已经分离了将这些特性转换为surfacegraph.py的代码,只将小部件的信号连接到surfacegraph.py中的函数中。下一章解释更多关于使用Q3DSurface的方法。
设置代理(Proxies)和数据
首先,我们实例化一个新的QSurfaceDataProxy,并将其附加到一个新的QSurface3DSeries上:
m_sqrtSinProxy = QSurfaceDataProxy() m_sqrtSinSeries = QSurface3DSeries(m_sqrtSinProxy)
然后我们用一个简单的平方根和正弦波数据填充代理。这是通过创建一个新的QSurfaceDataArray实例并向其添加QSurfaceDataRow元素来完成的。创建的QSurfaceDataArray被设置为QSurfaceDataProxy的数据阵列。
def fillSqrtSinProxy(self): stepX = (sampleMax - sampleMin) / float(sampleCountX - 1) stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1) dataArray = QSurfaceDataArray() dataArray.reserve(sampleCountZ) for i in range(0, sampleCountZ ): newRow = QSurfaceDataRow(sampleCountX) # Keep values within range bounds, since just adding step can cause minor drift due # to the rounding errors. z = qMin(sampleMax, (i * stepZ + sampleMin)) index = 0 for j in range(0, sampleCountX): x = qMin(sampleMax, (j * stepX + sampleMin)) R = qSqrt(z * z + x * x) + 0.01f y = (qSin(R) / R + 0.24f) * 1.61f (newRow)[index++].setPosition(QVector3D(x, y, z)) dataArray << newRow m_sqrtSinProxy.resetArray(dataArray)
接下来就可以在这个模块上进行修改,将平方根和正弦波数据更改为.msh中的网格点数据。
之前曾写过一个简陋的.msh文件读取二维网格点的代码,但是用Qchart显示不出来,可能是因为读取效率低或者QChart本身效率低:
path = 'Mesh/fluent.msh' lo = open(path, 'r+') lines = lo.readlines() x = [] y = [] for line in lines: t = line.split() # 以空格为分割进行划分 if len(t) == 2 and t[0] != '(2': x.append(float(t[0])) y.append(float(t[1]))
天真的想把这部分代码耦合到上面的Surface Example中,发现上面画网格的方式是:x轴坐标不变,y、z坐标变化,进而形成一个平行于y-z轴所在平面的曲线,所以在不进行较大修改的前提下不可以画出不规则网格。
虽然没有成功,但是之后可以继续研究,PySide中QtDataVisualization模块还是很强大的。
二、基于Matplotlib Widget 3D Example范例
Matplotlib Widget 3D Example - Qt for Python给出了基于Matplotlib与PuSide6的面显示模块代码。
我注意到Triangular Surface中的数据形式与CFD网格数据十分相似,三角形不规则网格划分。
def plot_triangular_surface(self): # Data radii = np.linspace(0.125, 1.0, 8) angles = np.linspace(0, 2 * np.pi, 36, endpoint=False)[..., np.newaxis] self.X = np.append(0, (radii * np.cos(angles)).flatten()) self.Y = np.append(0, (radii * np.sin(angles)).flatten()) self.Z = np.sin(-self.X * self.Y) self.set_canvas_table_configuration(len(self.X), (self.X, self.Y, self.Z)) self._ax.plot_trisurf(self.X, self.Y, self.Z, linewidth=0.2, antialiased=True) self.canvas.draw()
上面代码给出了绘制三角形网格组成曲面的代码,对这个稍加修改之后可以对.msh文件进行可视化,网格点数达到10000时速度也不是很慢,同时也可以实现拖拽、缩放、旋转等操作。
上面是修改完成后绘制.msh文件的效果,虽然界面还比较简陋,但是已经具备基本功能了。