关于 qgis-impl-vector-analysis
面向编写空间数据工作流的开发者,提供 PyQGIS 矢量分析参考。内容涵盖 API 模式,并提示几何、CRS 和输出处理中的常见问题。
主要功能
- 01空间要素筛选与索引
- 02几何运算和叠加分析
- 03按属性或位置连接
- 04将矢量数据写入 GeoPackage
- 05CRS 与几何安全指南
适用场景
- 01按范围或表达式筛选要素
- 02创建缓冲区和叠加结果
- 03连接多个矢量图层的属性
- 04将分析结果保存到磁盘
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ impertio-studio/ qgis-claude-skill-package --skill qgis-impl-vector-analysis安装后在 Claude Code 中输入/qgis-impl-vector-analysis确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/anti-patterns.mdexamples.mdmethods.md详细介绍
qgis-impl-vector-analysis
快速参考
核心类
| 类 | 用途 | 导入 |
|---|---|---|
QgsFeatureRequest | 按矩形、表达式或 FID 筛选要素 | qgis.core |
QgsSpatialIndex | 用于快速空间查询的内存 R 树 | qgis.core |
QgsGeometry | 几何操作(缓冲区、相交、包含) | qgis.core |
QgsVectorFileWriter | 将矢量图层写入磁盘(GPKG、SHP、GeoJSON) | qgis.core |
QgsCoordinateTransformContext | 用于输出的 CRS 转换上下文 | qgis.core |
processing | 运行 QGIS Processing 算法 | import processing |
关键 Processing 算法 ID
| 算法 | 用途 |
|---|---|
native:buffer | 在要素周围创建缓冲区 |
native:clip | 使用叠加图层裁剪输入图层 |
native:intersection | 对两个图层进行几何相交 |
native:union | 对两个图层进行几何并集 |
native:difference | 进行几何差集(A 减 B) |
native:symmetricaldifference | 获取属于 A 或 B、但不同时属于两者的要素 |
native:dissolve | 按属性值合并要素 |
native:joinattributestable | 按匹配的字段值连接属性 |
native:joinattributesbylocation | 根据几何关系进行空间连接 |
native:extractbyexpression | 提取符合表达式的要素 |
native:extractbylocation | 根据空间关系提取要素 |
native:fieldcalculator | 使用表达式计算字段值 |
重要警告
切勿在未先重投影的情况下,将 CRS 不同的图层用于叠加操作。Processing 算法会自动重投影,但 PyQGIS 几何方法不会。直接执行 QgsGeometry 操作前,务必确认 CRS 一致。
切勿对 NULL 几何调用 QgsGeometry 方法。执行任何几何操作前,务必检查 feature.hasGeometry()。NULL 几何会导致静默失败或崩溃。
切勿在使用 QgsVectorFileWriter.create() 后忘记调用 del writer。只有销毁 writer 对象后,文件才会写入磁盘。
切勿在批处理大数据集时使用 'OUTPUT': 'memory:'。内存图层会占用 RAM,并在 QGIS 关闭时丢失。务必写入 GeoPackage 以持久保存。
切勿假设 processing.run() 会修改输入图层。它始终会创建新的输出图层。通过 result['OUTPUT'] 访问结果。
当输入数据来自外部来源时,在叠加操作前务必使用 native:fixgeometries。无效几何会导致叠加算法静默失败或产生不完整结果。
在独立脚本中调用 processing.run() 前,务必初始化 Processing 框架:
from qgis.core import QgsApplication
import processing
from processing.core.Processing import Processing
Processing.initialize()
决策树:选择哪种叠加操作
What is your goal?
|
+-- Keep ONLY the area where both layers overlap
| --> native:intersection
|
+-- Combine ALL areas from both layers into one
| --> native:union
|
+-- Remove areas of layer B from layer A
| +-- Keep remainder of A only
| | --> native:difference
| +-- Keep remainder of BOTH A and B (exclude overlap)
| --> native:symmetricaldifference
|
+-- Cut layer A to the boundary of layer B
| --> native:clip
|
+-- Transfer attributes from one layer to another
+-- Based on matching field values
| --> native:joinattributestable
+-- Based on spatial relationship
| --> native:joinattributesbylocation
+-- Based on nearest feature
--> native:joinattributesbynearest
裁剪与相交
| 方面 | native:clip | native:intersection |
|---|---|---|
| 输出几何 | 与输入相同 | 可能在叠加边界处分割或合并 |
| 叠加属性 | 不包含 | 包含在输出中 |
| 使用场景 | 裁剪到研究区域 | 合并两个图层的数据 |
| 性能 | 更快 | 更慢(处理属性) |
必备模式
模式 1:使用要素请求进行空间查询
from qgis.core import QgsFeatureRequest, QgsRectangle
# Filter by bounding rectangle with exact geometry test
area = QgsRectangle(100.0, -1.0, 101.0, 0.0)
request = QgsFeatureRequest().setFilterRect(area)
request.setFlags(QgsFeatureRequest.ExactIntersect)
request.setLimit(100)
for feature in layer.getFeatures(request):
print(feature.id(), feature.geometry().asWkt())
模式 2:使用空间索引快速查询
from qgis.core import QgsSpatialIndex, QgsPointXY
index = QgsSpatialIndex(layer.getFeatures())
# Nearest neighbor: returns feature IDs
nearest_ids = index.nearestNeighbor(QgsPointXY(15.5, 47.1), 5)
# Bounding box intersection: returns feature IDs
bbox = QgsRectangle(14.0, 46.0, 17.0, 49.0)
intersecting_ids = index.intersects(bbox)
# Retrieve actual features by ID
for fid in nearest_ids:
feature = layer.getFeature(fid)
模式 3:通过 Processing 进行缓冲区分析
import processing
result = processing.run("native:buffer", {
'INPUT': layer,
'DISTANCE': 100,
'SEGMENTS': 5,
'END_CAP_STYLE': 0, # 0=Round, 1=Flat, 2=Square
'JOIN_STYLE': 0, # 0=Round, 1=Miter, 2=Bevel
'MITER_LIMIT': 2,
'DISSOLVE': False,
'OUTPUT': 'memory:'
})
buffered_layer = result['OUTPUT']
模式 4:通过 QgsGeometry 创建缓冲区(单个要素)
geom = feature.geometry()
if not geom.isNull():
buffered = geom.buffer(100.0, 5) # distance, segments
模式 5:叠加操作(相交)
import processing
result = processing.run("native:intersection", {
'INPUT': layer_a,
'OVERLAY': layer_b,
'INPUT_FIELDS': [],
'OVERLAY_FIELDS': [],
'OVERLAY_FIELDS_PREFIX': '',
'OUTPUT': 'memory:'
})
intersection_layer = result['OUTPUT']
模式 6:按字段值连接属性
result = processing.run("native:joinattributestable", {
'INPUT': layer_a,
'FIELD': 'id',
'INPUT_2': layer_b,
'FIELD_2': 'foreign_id',
'FIELDS_TO_COPY': [],
'METHOD': 0, # 0=one-to-many, 1=first match only
'DISCARD_NONMATCHING': False,
'PREFIX': '',
'OUTPUT': 'memory:'
})
模式 7:按位置进行空间连接
result = processing.run("native:joinattributesbylocation", {
'INPUT': target_layer,
'PREDICATE': [0], # 0=intersects, 1=contains, 2=equals,
# 3=touches, 4=overlaps, 5=within, 6=crosses
'JOIN': join_layer,
'JOIN_FIELDS': [],
'METHOD': 0, # 0=one-to-many, 1=one-to-first, 2=largest overlap
'DISCARD_NONMATCHING': False,
'PREFIX': '',
'OUTPUT': 'memory:'
})
模式 8:按属性融合
result = processing.run("native:dissolve", {
'INPUT': layer,
'FIELD': ['province'], # Dissolve field(s); empty list = dissolve all
'SEPARATE_DISJOINT': False,
'OUTPUT': 'memory:'
})
常见操作
字段计算(编辑缓冲区)
with edit(layer):
field_idx = layer.fields().indexOf('area_m2')
for feature in layer.getFeatures():
if feature.hasGeometry():
area = feature.geometry().area()
layer.changeAttributeValue(feature.id(), field_idx, area)
字段计算(Processing)
result = processing.run("native:fieldcalculator", {
'INPUT': layer,
'FIELD_NAME': 'area_m2',
'FIELD_TYPE': 0, # 0=Float, 1=Integer, 2=String, 3=Date
'FIELD_LENGTH': 10,
'FIELD_PRECISION': 3,
'FORMULA': '$area',
'OUTPUT': 'memory:'
})
要素选择
# Select by expression
layer.selectByExpression('"type" = \'highway\'')
# Iterate selected features
for feature in layer.selectedFeatures():
print(feature.id())
# Clear selection
layer.removeSelection()
按表达式提取要素
result = processing.run("native:extractbyexpression", {
'INPUT': layer,
'EXPRESSION': '"population" > 50000',
'OUTPUT': 'memory:'
})
按位置提取要素
result = processing.run("native:extractbylocation", {
'INPUT': layer,
'PREDICATE': [0], # 0=intersects
'INTERSECT': reference_layer,
'OUTPUT': 'memory:'
})
将输出写入 GeoPackage
from qgis.core import QgsVectorFileWriter, QgsCoordinateTransformContext
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = "GPKG"
save_options.fileEncoding = "UTF-8"
error = QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
"/path/to/output.gpkg",
QgsCoordinateTransformContext(),
save_options
)
逐个写入要素
from qgis.core import QgsVectorFileWriter, QgsWkbTypes, QgsCoordinateTransformContext
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = "GPKG"
writer = QgsVectorFileWriter.create(
"/path/to/output.gpkg",
layer.fields(),
QgsWkbTypes.Polygon,
layer.crs(),
QgsCoordinateTransformContext(),
save_options
)
for feature in layer.getFeatures():
writer.addFeature(feature)
del writer # ALWAYS delete to flush and close the file
使用统计信息进行聚合
result = processing.run("native:aggregate", {
'INPUT': layer,
'GROUP_BY': '"province"',
'AGGREGATES': [
{'aggregate': 'sum', 'delimiter': ',', 'input': '"population"',
'length': 10, 'name': 'total_pop', 'precision': 0, 'type': 6}
],
'OUTPUT': 'memory:'
})
参考链接
- references/methods.md -- QgsGeometry、QgsVectorFileWriter、QgsFeatureRequest、QgsSpatialIndex 的 API 签名,以及处理算法参数
- references/examples.md -- 使用真实数据的完整矢量分析工作流
- references/anti-patterns.md -- 常见的矢量分析错误及避免方法
官方来源
- https://docs.qgis.org/3.34/en/docs/pyqgis_developer_cookbook/vector.html
- https://docs.qgis.org/3.34/en/docs/pyqgis_developer_cookbook/geometry.html
- https://qgis.org/pyqgis/3.34/core/QgsGeometry.html
- https://qgis.org/pyqgis/3.34/core/QgsVectorFileWriter.html
- https://qgis.org/pyqgis/3.34/core/QgsSpatialIndex.html
评论
支持 Markdown