QGIS 软件是地理信息界最受欢迎的开源GIS软件之一。QGIS支持常见的矢量编辑、矢量分析功能,能够满足地理信息行业从业者的基本的地理数据处理需求。由于QGIS提供了便利的插件更新开发方式,支持Python、C++等语言编写的插件,如GRASS、OTB、EnMap等。其功能逐渐丰富,不仅能够流畅的浏览栅格数据(GDAL支持的数据类型)、浏览如地图、谷歌地图等网络服务发布的在线地图,对各类坐标系也很友好,支持三维图形显示,能够支持各类矢量数据(数据库、ESRI Shape file 、Geojson等格式)的显示、处理、编辑,配色和样式丰富程度不亚于ArcMap。
如此强大的地理信息平台,究竟是如何开发的、底层使用了哪些工具、运用了哪些技巧,终于有时间一探究竟。对我而言,QGIS无论从代码编写技巧设计模式角度,都非常值得学习。下面,将结合本人最近分析QGIS底层源代码的过程,将QGIS强大的功能是如何实现的逐步呈现出来。QGIS底层的CORE、GUI、ANALYSIS、App等模块的功能在此不再一一赘述,相关的讲解二次开发的博客有很多介绍。
本文涉及的QGIS绘制矢量包含了两层含义,第一层是用户交互式的绘制矢量,即常用的在栅格图层上面开展矢量化工作,实现图形绘制、几何体写出到文件的过程,第二层是通过读取SHAPE文件,将几何图形绘制到图形界面,并完成缩放、平移等操作的过程。
总体上,QGIS绘制矢量底层依赖了OGR,通过Orgprovider插件为QGIS-Core模块提供矢量Feature,通过底层依赖了QGraphicsView的Mapvanvas以及MapRender类渲染到图形界面。
- 首先介绍MapCanvas 类。这是QGIS绘图的基础类,可以理解为画板。在Qt里面属于图形视图(GraphicsView),GraphicsView 中可以包含很多的图形项目(GraphicsItem)。
MapCanvas: public QGraphicsView
{
//! graphics scene manages canvas items
QGraphicsScene *mScene = nullptr;
MapLayer 成员变量-即图层
MapRendererQImageJob 成员变量,渲染工。
}
从QGIS定义的MapLayer类来看,QGIS软件可以支持矢量、栅格、自定义插件图层和Mesh图层,这也是一个处理不同Provider类型插件提供的数据的关键标识。(Provider 模式后期再讲)。
MapLayer : public QObject
{
//! Types of layers that can be added to a map
enum LayerType
{
VectorLayer,
RasterLayer,
PluginLayer,
MeshLayer, //! 3D
};
}
QGIS定义了了一个私有的槽函数RefReshMap和refreshAllLayers函数。在类实例化时,即将RefReshMap函数与计时器绑定,当超过一定时间后即执行刷新函数,如下:
connect( mRefreshTimer, &QTimer::timeout, this, &HsllcMapCanvas::refreshMap );
在刷新过程中,QGIS需要判断是执行并行渲染还是序列渲染。
2.下面看并行渲染类:
*一个并行的渲染,最终渲染成一个QImage。
class MapRendererParallelJob : public MapRendererQImageJob
{
QImage mFinalImage;
}