地图样式与符号化

第九章 地图样式与符号化

9.1 符号化概述

9.1.1 什么是符号化

符号化是将地理数据以可视化方式呈现的过程,包括:

  • 颜色设置
  • 符号形状
  • 大小比例
  • 透明度
  • 标注样式

9.1.2 QGIS符号系统架构

QgsSymbol (符号基类)
├── QgsMarkerSymbol (点符号)
├── QgsLineSymbol (线符号)
└── QgsFillSymbol (面符号)

每种符号可包含多个符号图层(SymbolLayer)
实现复杂的叠加效果

9.1.3 渲染器类型

渲染器 适用场景 说明
单一符号 统一样式 所有要素相同
分类 分类数据 按类别区分
分级 数值数据 按数值范围
规则 复杂条件 基于表达式
点位移 重叠点 分散显示
聚类 密集点 聚合显示
热力图 密度分析 热度渲染
2.5D 立体效果 伪3D

9.2 点符号

9.2.1 简单标记

from qgis.core import (
    QgsMarkerSymbol,
    QgsSimpleMarkerSymbolLayer,
    QgsSingleSymbolRenderer
)
from qgis.PyQt.QtGui import QColor

# 创建简单标记
symbol = QgsMarkerSymbol.createSimple({
    'name': 'circle',        # 形状
    'color': '255,0,0,255',  # RGBA
    'size': '5',             # 大小
    'outline_color': 'black',
    'outline_width': '0.5'
})

# 应用到图层
renderer = QgsSingleSymbolRenderer(symbol)
layer.setRenderer(renderer)
layer.triggerRepaint()

可用形状

  • circle(圆形)
  • square(方形)
  • diamond(菱形)
  • pentagon(五边形)
  • hexagon(六边形)
  • triangle(三角形)
  • star(星形)
  • cross(十字)
  • cross2(X形)
  • arrow(箭头)

9.2.2 SVG标记

from qgis.core import QgsSvgMarkerSymbolLayer

# 使用SVG符号
symbol = QgsMarkerSymbol()
svg_layer = QgsSvgMarkerSymbolLayer('/path/to/icon.svg')
svg_layer.setSize(10)
svg_layer.setFillColor(QColor(255, 0, 0))
symbol.changeSymbolLayer(0, svg_layer)

9.2.3 字体标记

from qgis.core import QgsFontMarkerSymbolLayer

# 使用字体符号(如图标字体)
symbol = QgsMarkerSymbol()
font_layer = QgsFontMarkerSymbolLayer('Arial', 'A')
font_layer.setSize(10)
font_layer.setColor(QColor(255, 0, 0))
symbol.changeSymbolLayer(0, font_layer)

9.2.4 组合点符号

# 创建多层符号
symbol = QgsMarkerSymbol()

# 底层:大圆
base = QgsSimpleMarkerSymbolLayer()
base.setShape(QgsSimpleMarkerSymbolLayer.Circle)
base.setSize(10)
base.setColor(QColor(255, 255, 255))
base.setStrokeColor(QColor(0, 0, 0))

# 上层:小圆
top = QgsSimpleMarkerSymbolLayer()
top.setShape(QgsSimpleMarkerSymbolLayer.Circle)
top.setSize(5)
top.setColor(QColor(255, 0, 0))

symbol.changeSymbolLayer(0, base)
symbol.appendSymbolLayer(top)

9.3 线符号

9.3.1 简单线

from qgis.core import QgsLineSymbol, QgsSimpleLineSymbolLayer

symbol = QgsLineSymbol.createSimple({
    'color': '0,0,255',
    'width': '1',
    'line_style': 'solid'  # solid, dash, dot, dash_dot等
})

# 或使用符号图层
line_layer = QgsSimpleLineSymbolLayer()
line_layer.setColor(QColor(0, 0, 255))
line_layer.setWidth(1)
line_layer.setPenStyle(Qt.DashLine)

线型样式

  • solid(实线)
  • dash(虚线)
  • dot(点线)
  • dash_dot(点划线)
  • dash_dot_dot(双点划线)

9.3.2 标记线

from qgis.core import QgsMarkerLineSymbolLayer

# 沿线放置标记
marker_line = QgsMarkerLineSymbolLayer()
marker_line.setInterval(10)  # 间隔
marker_line.setPlacement(QgsMarkerLineSymbolLayer.Interval)

# 设置标记符号
marker = QgsMarkerSymbol.createSimple({'name': 'arrow'})
marker_line.setSubSymbol(marker)

9.3.3 渐变线

from qgis.core import QgsLineSymbol

# 线宽渐变
symbol = QgsLineSymbol()
line_layer = symbol.symbolLayer(0)

# 使用数据定义的宽度
from qgis.core import QgsProperty
line_layer.setDataDefinedProperty(
    QgsSymbolLayer.PropertyStrokeWidth,
    QgsProperty.fromExpression('"width_field"')
)

9.3.4 箭头线

from qgis.core import QgsArrowSymbolLayer

arrow = QgsArrowSymbolLayer()
arrow.setArrowWidth(2)
arrow.setArrowStartWidth(0.5)
arrow.setHeadLength(3)
arrow.setHeadThickness(2)
arrow.setIsCurved(False)

symbol = QgsLineSymbol()
symbol.changeSymbolLayer(0, arrow)

9.4 面符号

9.4.1 简单填充

from qgis.core import QgsFillSymbol, QgsSimpleFillSymbolLayer

symbol = QgsFillSymbol.createSimple({
    'color': '200,200,200',
    'outline_color': '0,0,0',
    'outline_width': '0.5',
    'style': 'solid'  # solid, horizontal, vertical, cross等
})

填充样式

  • solid(实心)
  • horizontal(水平线)
  • vertical(垂直线)
  • cross(交叉线)
  • b_diagonal(反斜线)
  • f_diagonal(斜线)
  • diagonal_x(X形)
  • dense1-7(不同密度点)

9.4.2 渐变填充

from qgis.core import QgsGradientFillSymbolLayer

gradient = QgsGradientFillSymbolLayer()
gradient.setColor(QColor(255, 255, 255))
gradient.setColor2(QColor(0, 0, 255))
gradient.setGradientType(QgsGradientFillSymbolLayer.Linear)
gradient.setCoordinateMode(QgsGradientFillSymbolLayer.Feature)
gradient.setGradientSpread(QgsGradientFillSymbolLayer.Pad)

9.4.3 图案填充

from qgis.core import QgsSVGFillSymbolLayer

svg_fill = QgsSVGFillSymbolLayer('/path/to/pattern.svg')
svg_fill.setPatternWidth(10)
svg_fill.setSvgFillColor(QColor(255, 0, 0))

9.4.4 质心填充

from qgis.core import QgsCentroidFillSymbolLayer

centroid = QgsCentroidFillSymbolLayer()
# 在多边形质心处放置点符号
marker = QgsMarkerSymbol.createSimple({'name': 'circle', 'size': '5'})
centroid.setSubSymbol(marker)

9.5 分类渲染

9.5.1 分类符号渲染器

from qgis.core import (
    QgsCategorizedSymbolRenderer,
    QgsRendererCategory,
    QgsMarkerSymbol
)

# 创建分类
categories = []

# 类别1
symbol1 = QgsMarkerSymbol.createSimple({'color': 'red'})
cat1 = QgsRendererCategory('类型A', symbol1, '类型A')
categories.append(cat1)

# 类别2
symbol2 = QgsMarkerSymbol.createSimple({'color': 'blue'})
cat2 = QgsRendererCategory('类型B', symbol2, '类型B')
categories.append(cat2)

# 创建渲染器
renderer = QgsCategorizedSymbolRenderer('type_field', categories)
layer.setRenderer(renderer)

9.5.2 自动分类

from qgis.core import QgsStyle

# 使用颜色渐变自动分类
style = QgsStyle.defaultStyle()
ramp = style.colorRamp('Spectral')

renderer = QgsCategorizedSymbolRenderer.createRenderer(
    layer,
    'category_field',
    QgsFillSymbol.createSimple({}),
    ramp
)
layer.setRenderer(renderer)

9.6 分级渲染

9.6.1 分级符号渲染器

from qgis.core import (
    QgsGraduatedSymbolRenderer,
    QgsRendererRange,
    QgsFillSymbol
)

# 创建分级
ranges = []

# 范围1: 0-100
symbol1 = QgsFillSymbol.createSimple({'color': '#ffffcc'})
range1 = QgsRendererRange(0, 100, symbol1, '0-100')
ranges.append(range1)

# 范围2: 100-500
symbol2 = QgsFillSymbol.createSimple({'color': '#fed976'})
range2 = QgsRendererRange(100, 500, symbol2, '100-500')
ranges.append(range2)

# 范围3: 500-1000
symbol3 = QgsFillSymbol.createSimple({'color': '#fd8d3c'})
range3 = QgsRendererRange(500, 1000, symbol3, '500-1000')
ranges.append(range3)

renderer = QgsGraduatedSymbolRenderer('value_field', ranges)
layer.setRenderer(renderer)

9.6.2 分级方法

# 使用分级方法
renderer = QgsGraduatedSymbolRenderer('population')

# 设置分类方法
# 0=等间距, 1=等计数, 2=自然断点, 3=标准差, 4=Pretty Breaks
renderer.setClassificationMethod(QgsClassificationJenks())

# 设置分类数
renderer.updateClasses(layer, 5)

layer.setRenderer(renderer)

9.6.3 分级颜色渐变

from qgis.core import QgsStyle, QgsGraduatedSymbolRenderer

style = QgsStyle.defaultStyle()
ramp = style.colorRamp('YlOrRd')

renderer = QgsGraduatedSymbolRenderer.createRenderer(
    layer,
    'value_field',
    5,  # 分类数
    QgsGraduatedSymbolRenderer.Jenks,  # 分类方法
    QgsFillSymbol.createSimple({}),
    ramp
)
layer.setRenderer(renderer)

9.7 规则渲染

9.7.1 规则渲染器

from qgis.core import QgsRuleBasedRenderer

# 创建根规则
root = QgsRuleBasedRenderer.Rule(None)

# 规则1: 大城市
symbol1 = QgsMarkerSymbol.createSimple({'color': 'red', 'size': '8'})
rule1 = QgsRuleBasedRenderer.Rule(symbol1)
rule1.setLabel('大城市')
rule1.setFilterExpression('"population" > 10000000')

# 规则2: 中等城市
symbol2 = QgsMarkerSymbol.createSimple({'color': 'orange', 'size': '5'})
rule2 = QgsRuleBasedRenderer.Rule(symbol2)
rule2.setLabel('中等城市')
rule2.setFilterExpression('"population" > 1000000 AND "population" <= 10000000')

# 规则3: 小城市
symbol3 = QgsMarkerSymbol.createSimple({'color': 'yellow', 'size': '3'})
rule3 = QgsRuleBasedRenderer.Rule(symbol3)
rule3.setLabel('小城市')
rule3.setFilterExpression('"population" <= 1000000')

root.appendChild(rule1)
root.appendChild(rule2)
root.appendChild(rule3)

renderer = QgsRuleBasedRenderer(root)
layer.setRenderer(renderer)

9.7.2 嵌套规则

# 创建嵌套规则结构
root = QgsRuleBasedRenderer.Rule(None)

# 父规则
parent = QgsRuleBasedRenderer.Rule(None)
parent.setLabel('已开发地区')
parent.setFilterExpression('"developed" = true')

# 子规则
child1 = QgsRuleBasedRenderer.Rule(QgsFillSymbol.createSimple({'color': 'red'}))
child1.setLabel('商业区')
child1.setFilterExpression('"type" = \'commercial\'')

child2 = QgsRuleBasedRenderer.Rule(QgsFillSymbol.createSimple({'color': 'yellow'}))
child2.setLabel('住宅区')
child2.setFilterExpression('"type" = \'residential\'')

parent.appendChild(child1)
parent.appendChild(child2)
root.appendChild(parent)

9.8 数据驱动样式

9.8.1 属性驱动大小

from qgis.core import QgsProperty, QgsSymbolLayer

symbol = QgsMarkerSymbol.createSimple({'name': 'circle'})
symbol_layer = symbol.symbolLayer(0)

# 根据字段值设置大小
symbol_layer.setDataDefinedProperty(
    QgsSymbolLayer.PropertySize,
    QgsProperty.fromExpression('sqrt("population") / 100')
)

9.8.2 属性驱动颜色

# 根据字段值设置颜色
symbol_layer.setDataDefinedProperty(
    QgsSymbolLayer.PropertyFillColor,
    QgsProperty.fromExpression('''
        CASE 
            WHEN "value" > 100 THEN 'red'
            WHEN "value" > 50 THEN 'yellow'
            ELSE 'green'
        END
    ''')
)

9.8.3 属性驱动旋转

# 根据字段值设置角度
symbol_layer.setDataDefinedProperty(
    QgsSymbolLayer.PropertyAngle,
    QgsProperty.fromField('rotation_angle')
)

9.9 标注

9.9.1 基本标注

from qgis.core import QgsPalLayerSettings, QgsVectorLayerSimpleLabeling

settings = QgsPalLayerSettings()
settings.fieldName = 'name'  # 标注字段
settings.enabled = True

# 文字格式
text_format = QgsTextFormat()
text_format.setFont(QFont('Arial', 12))
text_format.setSize(12)
text_format.setColor(QColor(0, 0, 0))
settings.setFormat(text_format)

# 应用标注
labeling = QgsVectorLayerSimpleLabeling(settings)
layer.setLabeling(labeling)
layer.setLabelsEnabled(True)

9.9.2 标注样式

# 背景
background = QgsTextBackgroundSettings()
background.setEnabled(True)
background.setType(QgsTextBackgroundSettings.ShapeRectangle)
background.setFillColor(QColor(255, 255, 255, 200))
text_format.setBackground(background)

# 缓冲区(描边)
buffer = QgsTextBufferSettings()
buffer.setEnabled(True)
buffer.setSize(1)
buffer.setColor(QColor(255, 255, 255))
text_format.setBuffer(buffer)

# 阴影
shadow = QgsTextShadowSettings()
shadow.setEnabled(True)
shadow.setOffsetDistance(2)
shadow.setOffsetUnit(QgsUnitTypes.RenderMillimeters)
shadow.setBlurRadius(3)
text_format.setShadow(shadow)

9.9.3 标注位置

# 点图层标注位置
settings.placement = QgsPalLayerSettings.OverPoint  # 在点上方

# 可选位置:
# OverPoint - 在点上
# AroundPoint - 围绕点
# Line - 沿线
# Curved - 弯曲沿线
# Horizontal - 水平
# Free - 自由
# OrderedPositionsAroundPoint - 优先位置

# 线图层
settings.placement = QgsPalLayerSettings.Line
settings.placementFlags = QgsPalLayerSettings.OnLine

# 面图层
settings.placement = QgsPalLayerSettings.OverPoint  # 质心

9.9.4 标注表达式

# 使用表达式作为标注
settings.isExpression = True
settings.fieldName = '''
    "name" || '\\n' || 
    format_number("population", 0) || ' 人'
'''

9.10 样式管理

9.10.1 保存和加载样式

# 保存样式到QML
layer.saveNamedStyle('/path/to/style.qml')

# 加载样式
layer.loadNamedStyle('/path/to/style.qml')

# 保存样式到SLD
layer.saveSldStyle('/path/to/style.sld')

9.10.2 样式管理器

设置 > 样式管理器

功能

  • 管理符号库
  • 导入/导出符号
  • 创建符号收藏夹
  • 管理颜色渐变

9.10.3 复制粘贴样式

# 复制样式
from qgis.core import QgsMapLayerStyle

style = QgsMapLayerStyle()
style.readFromLayer(source_layer)

# 粘贴到其他图层
style.writeToLayer(target_layer)

9.11 小结

本章详细介绍了QGIS中地图样式与符号化的各种方法:

关键要点

  1. 理解QGIS符号系统架构
  2. 掌握点、线、面符号的创建和配置
  3. 熟练使用分类和分级渲染
  4. 了解规则渲染的强大功能
  5. 掌握数据驱动样式的使用
  6. 能够配置专业的标注效果

良好的符号化是制作专业地图的关键。


上一章第08章 坐标参考系统与投影

下一章第10章 空间分析工具

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