1. 前言
在自己动手写3D库之前,我一直使用VisPy应对三维需求。这是一个高性能的可交互的2D/3D可视化函数库,但在后端显示上,我始终不能得心应手地驾驭它。2019年的元旦假期,我萌生了自己写3D应用库的念头,并立即付诸行动。三周之后,WxGL诞生。WxGL是一个基于PyOpenGL的三维数据展示库,以wx为显示后端,以加速渲染为第一追求目标。借助于WxPython这个后端,WxGL可以很好的融合Matplotlib等其他数据展示技术。
2. 安装
我的GitHub上有WxGL模块的完整源码文件,也可以直接使用以下命令安装我已经打包好的whl安装文件,目前的版本是0.5.4,如有必要,我会继续更新。
python -m pip install -i https://test.pypi.org/simple/ wxgl
WxGL依赖PyOpenGL,因此在安装WxGL之前,请先安装PyOpenGL。不过,如果直接使用pip安装的话,可能会有一些麻烦。当初我这样安装之后,运行 OpenGL 代码,得到了这样的错误信息:
NullFunctionError: Attempt to call an undefined function glutInit, check for bool(glutInit) before calling
原来,pip 默认安装的是32位版本的PyOpenGL,而我的操作系统是64位的。建议点击这里下载适合自己的版本,直接安装.whl文件。最终我是这样安装的:
pip install PyOpenGL-3.1.3b2-cp37-cp37m-win_amd64.whl
3. 类和方法
WxGL的容器名为WxGLScene,我称其为场景。每个场景可以使用addRegion()生成多个WxGLRegion对象,我称其为视区。在视区内可以创建模型,每个模型由一个或多个组件构成——所谓组件,可以理解为子模型。WxGLRegion提供了以下方法创建模型或组件:
- WxGLRegion.drawText() 绘制文本
- WxGLRegion.drawPoint() 绘制点
- WxGLRegion.drawLine() 绘制线段
- WxGLRegion.drawSurface() 绘制曲面
- WxGLRegion.drawMesh() 绘制网格
- WxGLRegion.drawVolume() 绘制体数据
- WxGLRegion.drawAxes() 绘制坐标
- WxGLRegion.drawColorBar() 绘制绘制colorBar
4. 应用示例
接下来,我们使用WxGL来演示一下,如何将下面这张全球等经纬投影模式的疫情地图,变成一个可以任意缩放和旋转的三维地球。全部代码,包括注释,刚刚40行。里面用到了一个矢量字库文件,请根据自己的运行环境修改路径。疫情地图,可以下载本文插图,也可以参考我的另一篇博文《Python实战:抓肺炎疫情实时数据,画2019-nCoV疫情地图》,自行生成更高分辨率的疫情地图。
2019-nCoV疫情地图(全球等经纬投影模式):
earth_2019nCoV.py
# -*- coding: utf-8 -*-
import wx
import numpy as np
from PIL import Image
from wxgl.scene import *
from wxgl.colormap import *
class mainFrame(wx.Frame):
'''程序主窗口类,继承自wx.Frame'''
def __init__(self):
wx.Frame.__init__(self, None, -1, '地球模型上的2019-nCoV疫情地图', style=wx.DEFAULT_FRAME_STYLE)
self.Maximize()
# 从等经纬地图上读取经纬度网格上的每一个格点的颜色
c = np.array(Image.open('res/e0.jpg'))/255
# 生成和等经纬地图分辨率一致的经纬度网格,计算经纬度网格上的每一个格点的空间坐标(x,y,z)
lats, lons = np.mgrid[np.pi/2:-np.pi/2:complex(0,c.shape[0]), 0:2*np.pi:complex(0,c.shape[1])]
x = np.cos(lats)*np.cos(lons)
y = np.cos(lats)*np.sin(lons)
z = np.sin(lats)
self.scene = WxGLScene(self, r"C:\Windows\Fonts\simfang.ttf", bg=[0,0,0,0])
self.scene.setPosture(elevation=0, azimuth=120, save=True)
self.master = self.scene.addRegion((0,0,1,1))
self.master.drawMesh('earth', x, y, z, c)
self.master.update()
class mainApp(wx.App):
def OnInit(self):
self.Frame = mainFrame()
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()
运行效果如下:
更为复杂的应用,请参考我的另一篇博文:《wxPython + pyOpenGL,打造三维数据分析的利器》
转载:https://blog.csdn.net/xufive/article/details/104211044