核心架构与模块设计

第三章 核心架构与模块设计

3.1 QGIS整体架构概览

3.1.1 架构设计理念

QGIS采用分层架构设计,遵循以下核心原则:

  • 模块化设计:各功能模块相对独立,便于维护和扩展
  • 开放标准:遵循OGC标准,支持多种数据格式
  • 可扩展性:通过插件机制支持功能扩展
  • 跨平台:基于Qt框架实现跨平台支持
  • 脚本友好:完整的Python API支持自动化

3.1.2 架构层次图

┌─────────────────────────────────────────────────────────────┐
│                        应用层                                │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│   │ QGIS Desktop│  │ QGIS Server │  │   QField    │        │
│   └─────────────┘  └─────────────┘  └─────────────┘        │
├─────────────────────────────────────────────────────────────┤
│                        GUI层                                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              qgis_gui (Qt Widgets)                   │   │
│   └─────────────────────────────────────────────────────┘   │
├─────────────────────────────────────────────────────────────┤
│                       核心层                                 │
│   ┌────────────┐  ┌────────────┐  ┌────────────┐          │
│   │  qgis_core │  │qgis_analysis│  │  qgis_3d   │          │
│   └────────────┘  └────────────┘  └────────────┘          │
├─────────────────────────────────────────────────────────────┤
│                       提供者层                               │
│   ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐  │
│   │  OGR   │ │  GDAL  │ │ PostGIS │ │  WMS   │ │  WFS   │  │
│   └────────┘ └────────┘ └────────┘ └────────┘ └────────┘  │
├─────────────────────────────────────────────────────────────┤
│                       底层库                                 │
│   ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐  │
│   │   Qt   │ │  GDAL  │ │  PROJ  │ │  GEOS  │ │ SQLite │  │
│   └────────┘ └────────┘ └────────┘ └────────┘ └────────┘  │
└─────────────────────────────────────────────────────────────┘

3.1.3 源代码结构

QGIS源代码组织在多个目录中:

qgis/
├── src/
│   ├── core/           # 核心库(不依赖GUI)
│   ├── gui/            # GUI组件
│   ├── analysis/       # 空间分析功能
│   ├── 3d/             # 3D功能
│   ├── app/            # Desktop应用程序
│   ├── server/         # QGIS Server
│   ├── providers/      # 数据提供者
│   │   ├── ogr/
│   │   ├── gdal/
│   │   ├── postgres/
│   │   ├── wms/
│   │   ├── wfs/
│   │   └── ...
│   ├── plugins/        # 核心插件
│   └── ui/             # UI定义文件
├── python/             # Python绑定
│   ├── core/
│   ├── gui/
│   ├── analysis/
│   └── plugins/        # 默认Python插件
├── tests/              # 测试代码
├── resources/          # 资源文件
└── doc/                # 文档

3.2 核心模块详解

3.2.1 qgis_core模块

qgis_core是QGIS的核心库,提供不依赖GUI的基础功能:

主要类别

类别 主要类 功能
几何 QgsGeometry, QgsPoint, QgsPolygon 几何对象操作
要素 QgsFeature, QgsFields, QgsAttributes 要素和属性管理
图层 QgsVectorLayer, QgsRasterLayer 数据图层
项目 QgsProject, QgsMapSettings 项目管理
坐标系 QgsCoordinateReferenceSystem CRS处理
渲染 QgsMapRenderer, QgsSymbol 地图渲染
表达式 QgsExpression, QgsExpressionContext 表达式引擎

核心类关系图

QgsProject (项目容器)
    │
    ├── QgsLayerTree (图层树)
    │
    ├── QgsMapLayer (图层基类)
    │   ├── QgsVectorLayer (矢量图层)
    │   │   ├── QgsFeatureIterator (要素迭代器)
    │   │   ├── QgsFeature (要素)
    │   │   │   ├── QgsGeometry (几何)
    │   │   │   └── QgsAttributes (属性)
    │   │   └── QgsRenderer (渲染器)
    │   │
    │   └── QgsRasterLayer (栅格图层)
    │       └── QgsRasterDataProvider (数据提供者)
    │
    └── QgsCoordinateReferenceSystem (坐标系)

3.2.2 qgis_gui模块

qgis_gui提供图形界面组件:

主要组件

组件 功能
地图画布 QgsMapCanvas 地图显示和交互
图层面板 QgsLayerTreeView 图层管理界面
属性表 QgsAttributeTableView 属性编辑
字段编辑器 QgsFieldValidator 字段值验证
坐标选择器 QgsCrsSelector CRS选择界面
颜色按钮 QgsColorButton 颜色选择
表达式构建器 QgsExpressionBuilderWidget 表达式编辑

地图工具类层次

QgsMapTool (基类)
├── QgsMapToolPan (平移)
├── QgsMapToolZoom (缩放)
├── QgsMapToolIdentify (识别)
├── QgsMapToolSelect (选择)
├── QgsMapToolEmitPoint (点发射)
└── QgsMapToolEdit (编辑工具基类)
    ├── QgsMapToolAddFeature (添加要素)
    ├── QgsMapToolMoveFeature (移动要素)
    └── QgsMapToolDeletePart (删除部分)

3.2.3 qgis_analysis模块

提供空间分析功能:

分析功能分类

类别 类/命名空间 功能
矢量分析 QgsGeometryAnalyzer 缓冲、叠加、裁剪
栅格分析 QgsRasterCalculator 栅格计算
插值 QgsInterpolator 空间插值
网络分析 QgsNetworkAnalysis 路径分析
地形分析 QgsRasterTerrainAnalysis 坡度、坡向

3.2.4 qgis_3d模块

3D可视化功能(QGIS 3.0+):

主要类

功能
Qgs3DMapScene 3D场景管理
Qgs3DMapSettings 3D地图设置
QgsPhongMaterialSettings 材质设置
QgsTerrainGenerator 地形生成
Qgs3DSymbol 3D符号

3.3 数据提供者架构

3.3.1 提供者接口

数据提供者是QGIS与数据源之间的桥梁:

QgsDataProvider (抽象基类)
├── QgsVectorDataProvider (矢量数据)
│   ├── QgsOgrProvider (OGR/Shapefile等)
│   ├── QgsPostgresProvider (PostgreSQL/PostGIS)
│   ├── QgsDelimitedTextProvider (CSV/文本)
│   ├── QgsMemoryProvider (内存图层)
│   └── QgsSpatiaLiteProvider (SpatiaLite)
│
└── QgsRasterDataProvider (栅格数据)
    ├── QgsGdalProvider (GDAL)
    └── QgsWmsProvider (WMS服务)

3.3.2 矢量数据提供者

矢量提供者实现QgsVectorDataProvider接口:

核心方法

class QgsVectorDataProvider : public QgsDataProvider
{
public:
    // 要素访问
    virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request);
    virtual long featureCount() const;
    
    // 字段信息
    virtual QgsFields fields() const;
    
    // 能力查询
    virtual Capabilities capabilities() const;
    
    // 编辑操作
    virtual bool addFeatures(QgsFeatureList &features);
    virtual bool deleteFeatures(const QgsFeatureIds &ids);
    virtual bool changeAttributeValues(const QgsChangedAttributesMap &map);
    virtual bool changeGeometryValues(const QgsGeometryMap &map);
    
    // 范围
    virtual QgsRectangle extent() const;
    
    // CRS
    virtual QgsCoordinateReferenceSystem crs() const;
};

提供者能力标志

enum Capability
{
    NoCapabilities = 0,
    AddFeatures = 1,
    DeleteFeatures = 1 << 1,
    ChangeAttributeValues = 1 << 2,
    AddAttributes = 1 << 3,
    DeleteAttributes = 1 << 4,
    ChangeGeometries = 1 << 5,
    SelectAtId = 1 << 6,
    CreateSpatialIndex = 1 << 7,
    SelectGeometryAtId = 1 << 8,
    TransactionSupport = 1 << 9,
    CircularGeometries = 1 << 10,
    // ...
};

3.3.3 栅格数据提供者

class QgsRasterDataProvider : public QgsDataProvider
{
public:
    // 波段信息
    virtual int bandCount() const;
    virtual Qgis::DataType dataType(int bandNo) const;
    
    // 数据读取
    virtual QgsRasterBlock *block(int bandNo, const QgsRectangle &extent, int width, int height);
    
    // 统计信息
    virtual QgsRasterBandStats bandStatistics(int bandNo);
    
    // 颜色表
    virtual QList<QgsColorRampShader::ColorRampItem> colorTable(int bandNo) const;
    
    // 元数据
    virtual QString metadata() const;
};

3.3.4 Web服务提供者

WMS提供者

# 使用WMS提供者
uri = "url=https://example.com/wms&layers=layer1&format=image/png&crs=EPSG:4326"
layer = QgsRasterLayer(uri, "WMS Layer", "wms")

WFS提供者

# 使用WFS提供者
uri = "https://example.com/wfs?typename=ns:layer&version=2.0.0"
layer = QgsVectorLayer(uri, "WFS Layer", "WFS")

3.4 插件架构

3.4.1 插件类型

QGIS支持两种插件类型:

类型 语言 特点
Python插件 Python 易于开发,大多数插件
C++插件 C++ 高性能,核心功能扩展

3.4.2 Python插件结构

my_plugin/
├── __init__.py           # 插件入口
├── metadata.txt          # 元数据
├── my_plugin.py          # 主模块
├── my_plugin_dialog.py   # 对话框
├── resources.qrc         # Qt资源
├── resources_rc.py       # 编译的资源
├── my_plugin_dialog_base.ui  # UI定义
├── icon.png              # 图标
├── help/                 # 帮助文档
└── i18n/                 # 翻译文件

metadata.txt格式

[general]
name=My Plugin
qgisMinimumVersion=3.0
description=This is a plugin description
version=1.0.0
author=Author Name
email=author@example.com

about=Detailed plugin description

tracker=https://github.com/author/plugin/issues
repository=https://github.com/author/plugin

tags=analysis, vector

homepage=https://example.com
category=Plugins
icon=icon.png

experimental=False
deprecated=False

3.4.3 插件接口

# __init__.py
def classFactory(iface):
    """加载插件类"""
    from .my_plugin import MyPlugin
    return MyPlugin(iface)


# my_plugin.py
class MyPlugin:
    def __init__(self, iface):
        """构造函数
        
        :param iface: QgisInterface实例
        """
        self.iface = iface
        
    def initGui(self):
        """初始化GUI,添加菜单和工具栏"""
        self.action = QAction("My Plugin", self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&My Plugin", self.action)
        
    def unload(self):
        """卸载插件"""
        self.iface.removePluginMenu("&My Plugin", self.action)
        self.iface.removeToolBarIcon(self.action)
        
    def run(self):
        """执行插件功能"""
        pass

3.4.4 QgisInterface

QgisInterface是插件与QGIS主程序交互的接口:

# 常用方法
iface.mapCanvas()           # 获取地图画布
iface.activeLayer()         # 获取当前活动图层
iface.addVectorLayer()      # 添加矢量图层
iface.addRasterLayer()      # 添加栅格图层
iface.messageBar()          # 消息栏
iface.mainWindow()          # 主窗口
iface.layerTreeView()       # 图层树视图

# 菜单操作
iface.addPluginToMenu()     # 添加到插件菜单
iface.addPluginToVectorMenu()   # 添加到矢量菜单
iface.addPluginToRasterMenu()   # 添加到栅格菜单

# 工具栏操作
iface.addToolBarIcon()      # 添加工具栏图标
iface.addToolBar()          # 添加工具栏

3.5 Processing框架

3.5.1 Processing架构

Processing是QGIS的地理处理框架:

Processing Framework
├── QgsProcessingRegistry (算法注册表)
│   └── QgsProcessingProvider (算法提供者)
│       └── QgsProcessingAlgorithm (算法)
│
├── QgsProcessingContext (处理上下文)
├── QgsProcessingFeedback (反馈机制)
│
└── GUI组件
    ├── ProcessingToolbox (工具箱面板)
    ├── AlgorithmDialog (算法对话框)
    └── ModelDesigner (模型设计器)

3.5.2 算法提供者

内置的算法提供者:

提供者 说明
native QGIS原生算法
qgis QGIS Python算法
gdal GDAL/OGR工具
grass7 GRASS GIS算法
saga SAGA GIS算法
script 用户脚本
model 处理模型

3.5.3 自定义算法

from qgis.processing import alg

@alg(name='my_algorithm', label='My Algorithm',
     group='My Tools', group_label='My Tools')
@alg.input(type=alg.SOURCE, name='INPUT', label='Input layer')
@alg.input(type=alg.DISTANCE, name='BUFFER', label='Buffer distance',
           default=10.0)
@alg.input(type=alg.SINK, name='OUTPUT', label='Output layer')
def my_algorithm(instance, parameters, context, feedback, inputs):
    """
    自定义处理算法
    """
    source = instance.parameterAsSource(parameters, 'INPUT', context)
    buffer_dist = instance.parameterAsDouble(parameters, 'BUFFER', context)
    
    (sink, dest_id) = instance.parameterAsSink(
        parameters, 'OUTPUT', context,
        source.fields(),
        QgsWkbTypes.Polygon,
        source.sourceCrs()
    )
    
    total = source.featureCount()
    for current, feature in enumerate(source.getFeatures()):
        if feedback.isCanceled():
            break
        
        # 创建缓冲区
        buffered_geom = feature.geometry().buffer(buffer_dist, 5)
        
        new_feature = QgsFeature()
        new_feature.setGeometry(buffered_geom)
        new_feature.setAttributes(feature.attributes())
        sink.addFeature(new_feature)
        
        feedback.setProgress(int(current / total * 100))
    
    return {'OUTPUT': dest_id}

3.5.4 算法参数类型

参数类型 常量 说明
矢量图层 SOURCE 输入矢量源
栅格图层 RASTER 输入栅格
要素输出 SINK 矢量输出
栅格输出 RASTER_DESTINATION 栅格输出
数值 NUMBER 数字输入
距离 DISTANCE 距离值
字符串 STRING 文本输入
布尔 BOOLEAN 是/否
枚举 ENUM 下拉选择
字段 FIELD 字段选择
表达式 EXPRESSION 表达式
CRS CRS 坐标系
范围 EXTENT 空间范围

3.6 渲染系统

3.6.1 渲染架构

QgsMapCanvas
    │
    ├── QgsMapSettings (地图设置)
    │   ├── 范围、CRS、图层列表
    │   └── 输出大小、DPI
    │
    ├── QgsMapRendererJob (渲染作业)
    │   ├── QgsMapRendererSequentialJob (顺序)
    │   └── QgsMapRendererParallelJob (并行)
    │
    └── 图层渲染
        ├── QgsVectorLayerRenderer (矢量)
        └── QgsRasterLayerRenderer (栅格)

3.6.2 矢量渲染器

矢量图层支持多种渲染器:

渲染器 说明
单一符号 QgsSingleSymbolRenderer 所有要素相同样式
分类 QgsCategorizedSymbolRenderer 按属性分类
分级 QgsGraduatedSymbolRenderer 按数值分级
规则 QgsRuleBasedRenderer 基于规则
点位移 QgsPointDisplacementRenderer 重叠点处理
热力图 QgsHeatmapRenderer 热力图
2.5D Qgs25DRenderer 伪3D效果

3.6.3 符号系统

QgsSymbol (符号基类)
├── QgsMarkerSymbol (点符号)
│   └── QgsMarkerSymbolLayer
│       ├── QgsSimpleMarkerSymbolLayer
│       ├── QgsSvgMarkerSymbolLayer
│       ├── QgsFontMarkerSymbolLayer
│       └── ...
│
├── QgsLineSymbol (线符号)
│   └── QgsLineSymbolLayer
│       ├── QgsSimpleLineSymbolLayer
│       ├── QgsMarkerLineSymbolLayer
│       └── ...
│
└── QgsFillSymbol (面符号)
    └── QgsFillSymbolLayer
        ├── QgsSimpleFillSymbolLayer
        ├── QgsGradientFillSymbolLayer
        ├── QgsSVGFillSymbolLayer
        └── ...

3.6.4 栅格渲染器

渲染器 说明
MultiBandColor 多波段彩色合成
PalettedRaster 调色板渲染
SingleBandGray 单波段灰度
SingleBandPseudoColor 单波段伪彩色
Hillshade 山体阴影
Contour 等值线

3.7 表达式引擎

3.7.1 表达式系统架构

QgsExpression (表达式解析器)
    │
    ├── 词法分析 → 语法分析 → 语法树
    │
    ├── QgsExpressionContext (上下文)
    │   ├── QgsExpressionContextScope (作用域)
    │   │   ├── 全局变量
    │   │   ├── 项目变量
    │   │   └── 图层变量
    │   └── QgsFeature (当前要素)
    │
    └── 函数库
        ├── 数学函数
        ├── 字符串函数
        ├── 几何函数
        ├── 日期函数
        ├── 聚合函数
        └── 自定义函数

3.7.2 表达式语法

-- 字段引用
"field_name"

-- 算术运算
"population" / "area"

-- 条件表达式
CASE 
    WHEN "type" = 'A' THEN 'Category A'
    WHEN "type" = 'B' THEN 'Category B'
    ELSE 'Other'
END

-- 几何函数
$area                       -- 当前要素面积
$length                     -- 当前要素长度
buffer($geometry, 100)      -- 缓冲区
centroid($geometry)         -- 质心

-- 聚合函数
aggregate('layer', 'sum', "value")
count("field", group_by:="category")

-- 变量引用
@project_title
@layer_name

3.7.3 自定义表达式函数

from qgis.core import qgsfunction

@qgsfunction(args='auto', group='Custom')
def my_function(value1, value2, feature, parent):
    """
    自定义表达式函数
    
    <h4>语法</h4>
    <p>my_function(value1, value2)</p>
    
    <h4>示例</h4>
    <p>my_function(10, 20) → 30</p>
    """
    return value1 + value2

# 注册函数
QgsExpression.registerFunction(my_function)

# 使用后注销
QgsExpression.unregisterFunction('my_function')

3.8 坐标转换系统

3.8.1 CRS架构

QgsCoordinateReferenceSystem
    │
    ├── 创建方式
    │   ├── fromEpsgId(4326)
    │   ├── fromProj(proj_string)
    │   ├── fromWkt(wkt_string)
    │   └── fromOgcWmsCrs("EPSG:4326")
    │
    ├── 属性
    │   ├── authid()           # "EPSG:4326"
    │   ├── description()      # "WGS 84"
    │   ├── mapUnits()         # 地图单位
    │   └── isGeographic()     # 是否地理坐标系
    │
    └── QgsCoordinateTransform (坐标转换)
        ├── transform(point)
        ├── transformBoundingBox(rect)
        └── transformCoords(count, x, y, z)

3.8.2 坐标转换示例

from qgis.core import (
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsProject,
    QgsPointXY
)

# 定义源和目标CRS
source_crs = QgsCoordinateReferenceSystem("EPSG:4326")  # WGS84
dest_crs = QgsCoordinateReferenceSystem("EPSG:32650")   # UTM 50N

# 创建转换对象
transform = QgsCoordinateTransform(
    source_crs, 
    dest_crs, 
    QgsProject.instance()
)

# 转换点坐标
point = QgsPointXY(116.0, 39.0)  # 北京附近
transformed = transform.transform(point)
print(f"转换后: {transformed.x()}, {transformed.y()}")

# 反向转换
reverse_transform = QgsCoordinateTransform(
    dest_crs, 
    source_crs, 
    QgsProject.instance()
)
original = reverse_transform.transform(transformed)

3.8.3 基准面转换

# 获取可用的基准面转换
transforms = QgsCoordinateTransform.datumTransformations(
    source_crs, dest_crs
)

for t in transforms:
    print(f"转换: {t.sourceTransformId} -> {t.destinationTransformId}")
    print(f"  精度: {t.accuracy}")
    
# 使用特定的基准面转换
context = QgsCoordinateTransformContext()
context.addCoordinateOperation(source_crs, dest_crs, "proj_string")

3.9 消息和日志系统

3.9.1 消息系统

from qgis.core import Qgis
from qgis.utils import iface

# 消息栏消息
iface.messageBar().pushMessage(
    "标题",
    "消息内容",
    level=Qgis.Info,  # Info, Warning, Critical, Success
    duration=5  # 秒,0表示不自动消失
)

# 带操作的消息
from qgis.PyQt.QtWidgets import QPushButton

def show_help():
    # 显示帮助
    pass

widget = iface.messageBar().createMessage("信息", "点击查看更多")
button = QPushButton("详情")
button.clicked.connect(show_help)
widget.layout().addWidget(button)
iface.messageBar().pushWidget(widget, Qgis.Info)

3.9.2 日志系统

from qgis.core import QgsMessageLog, Qgis

# 记录消息
QgsMessageLog.logMessage(
    "这是一条日志消息",
    tag="MyPlugin",
    level=Qgis.Info
)

# 日志级别
# Qgis.Info - 信息
# Qgis.Warning - 警告  
# Qgis.Critical - 错误
# Qgis.Success - 成功

# 监听日志消息
def log_handler(message, tag, level):
    print(f"[{tag}] {level}: {message}")

QgsMessageLog.instance().messageReceived.connect(log_handler)

3.10 设置和配置

3.10.1 QgsSettings

from qgis.core import QgsSettings

settings = QgsSettings()

# 读取设置
value = settings.value("plugin/my_setting", defaultValue="default")

# 写入设置
settings.setValue("plugin/my_setting", "new_value")

# 分组操作
settings.beginGroup("plugin")
settings.setValue("setting1", "value1")
settings.setValue("setting2", "value2")
settings.endGroup()

# 删除设置
settings.remove("plugin/my_setting")

3.10.2 项目设置

from qgis.core import QgsProject

project = QgsProject.instance()

# 读取项目变量
value = project.readEntry("section", "key", "default")[0]

# 写入项目变量
project.writeEntry("section", "key", "value")

# 自定义属性
project.setCustomProperty("my_property", "value")
prop = project.customProperty("my_property")

# 项目元数据
project.setTitle("My Project")
project.setAuthor("Author Name")

3.11 小结

本章详细介绍了QGIS的核心架构和模块设计:

关键要点

  1. QGIS采用分层模块化架构,核心库不依赖GUI
  2. 数据提供者架构支持多种数据源
  3. 插件系统允许功能扩展
  4. Processing框架提供统一的地理处理能力
  5. 渲染系统支持丰富的可视化选项
  6. 表达式引擎是数据驱动样式的核心

理解这些架构概念对于高效使用QGIS和进行二次开发至关重要。


上一章第02章 安装与环境配置

下一章第04章 用户界面详解

posted @ 2026-01-08 14:04  我才是银古  阅读(26)  评论(0)    收藏  举报