mcpField
Q
qgis-impl-vector-analysis

qgis-impl-vector-analysis

github.com/impertio-studio数据与数据库3948 次安装31 周前更新
代码仓库

关于 qgis-impl-vector-analysis

面向编写空间数据工作流的开发者,提供 PyQGIS 矢量分析参考。内容涵盖 API 模式,并提示几何、CRS 和输出处理中的常见问题。

主要功能

  1. 01空间要素筛选与索引
  2. 02几何运算和叠加分析
  3. 03按属性或位置连接
  4. 04将矢量数据写入 GeoPackage
  5. 05CRS 与几何安全指南

适用场景

  1. 01按范围或表达式筛选要素
  2. 02创建缓冲区和叠加结果
  3. 03连接多个矢量图层的属性
  4. 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.md
examples.md
methods.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:clipnative: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:'
})

参考链接

官方来源

评论

支持 Markdown