开源我的3D库WxGL:40行代码将疫情地图变成三维地球模型

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,打造三维数据分析的利器》

发布了89 篇原创文章 · 获赞 9427 · 访问量 121万+

猜你喜欢

转载自blog.csdn.net/xufive/article/details/104211044