@dsh-gis/dsh-opengis-skill 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +19 -0
- package/CHANGELOG.md +96 -0
- package/LICENSE +21 -21
- package/README.md +91 -30
- package/THIRD_PARTY_NOTICES.md +37 -10
- package/assets/gdal/reference/raster-tools.md +538 -538
- package/assets/gdal/reference/vector-tools.md +149 -149
- package/assets/gdal-api/reference/raster-api.md +424 -424
- package/assets/gdal-api/reference/vector-api.md +724 -724
- package/assets/geometry-api-net/reference/geometry-types.md +243 -243
- package/assets/geopandas/reference/core-api.md +221 -221
- package/assets/geotools/reference/raster-rendering.md +108 -108
- package/assets/geotools/reference/vector-io.md +149 -149
- package/assets/jts/reference/geometry-operations.md +303 -303
- package/assets/mapsui/SKILL.md +283 -283
- package/assets/opengis-all/reference/data-stages.md +608 -608
- package/assets/opengis-all/reference/workflow-cheatsheets.md +324 -324
- package/assets/opengis-utils-for-java/reference/common-tasks.md +384 -384
- package/assets/opengis-utils-for-net/reference/code-patterns.md +124 -124
- package/assets/opengis-utils-for-net/reference/util-classes.md +291 -291
- package/assets/pyqgis/reference/processing-rendering.md +292 -292
- package/assets/pyqgis/reference/vector-raster-layers.md +318 -318
- package/assets/qgis-process/SKILL.md +414 -414
- package/assets/qgis-process/reference/algorithm-cheatsheet.md +194 -194
- package/assets/shapely/reference/operations-reference.md +199 -199
- package/cordis.patch.yml +6 -3
- package/lib/catalog.d.ts +50 -0
- package/lib/catalog.js +238 -0
- package/lib/index.d.ts +47 -6
- package/lib/index.js +32 -44
- package/lib/markdown-links.d.ts +11 -0
- package/lib/markdown-links.js +103 -0
- package/lib/skill-file.js +104 -17
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +11 -5
- package/upstream.json +64 -2
|
@@ -1,318 +1,318 @@
|
|
|
1
|
-
# PyQGIS Vector and Raster Layer Operations Reference
|
|
2
|
-
|
|
3
|
-
> 这是 [../SKILL.md](../SKILL.md) 的补充文件,收录矢量/栅格图层操作的完整 API 与示例。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 矢量图层操作
|
|
8
|
-
|
|
9
|
-
### 加载矢量图层
|
|
10
|
-
|
|
11
|
-
```python
|
|
12
|
-
from qgis.core import QgsVectorLayer
|
|
13
|
-
|
|
14
|
-
# 从文件加载
|
|
15
|
-
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
|
|
16
|
-
|
|
17
|
-
# 从 GeoPackage 加载指定图层
|
|
18
|
-
layer = QgsVectorLayer("/data/data.gpkg|layername=rivers", "rivers", "ogr")
|
|
19
|
-
|
|
20
|
-
# 从 PostGIS 加载
|
|
21
|
-
uri = 'dbname=\'gis\' host=localhost port=5432 user=\'postgres\' table="public"."parcels" (geom)'
|
|
22
|
-
layer = QgsVectorLayer(uri, "parcels", "postgres")
|
|
23
|
-
|
|
24
|
-
# 内存图层
|
|
25
|
-
layer = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer&field=name:string(50)", "temp", "memory")
|
|
26
|
-
|
|
27
|
-
# 验证
|
|
28
|
-
if not layer.isValid():
|
|
29
|
-
print("图层加载失败!")
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### 遍历要素
|
|
33
|
-
|
|
34
|
-
```python
|
|
35
|
-
for feature in layer.getFeatures():
|
|
36
|
-
geom = feature.geometry()
|
|
37
|
-
attrs = feature.attributes()
|
|
38
|
-
print(feature.id(), geom.asWkt(), attrs)
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### 按条件查询要素
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
from qgis.core import QgsFeatureRequest
|
|
45
|
-
|
|
46
|
-
# 按属性过滤
|
|
47
|
-
request = QgsFeatureRequest().setFilterExpression('"population" > 10000')
|
|
48
|
-
for feature in layer.getFeatures(request):
|
|
49
|
-
print(feature["name"], feature["population"])
|
|
50
|
-
|
|
51
|
-
# 按空间范围过滤
|
|
52
|
-
from qgis.core import QgsRectangle
|
|
53
|
-
rect = QgsRectangle(116.0, 39.0, 117.0, 40.0)
|
|
54
|
-
request = QgsFeatureRequest().setFilterRect(rect)
|
|
55
|
-
for feature in layer.getFeatures(request):
|
|
56
|
-
print(feature.id())
|
|
57
|
-
|
|
58
|
-
# 限制返回字段(提升性能)
|
|
59
|
-
request = QgsFeatureRequest().setSubsetOfAttributes(["name", "area"], layer.fields())
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### 编辑要素
|
|
63
|
-
|
|
64
|
-
```python
|
|
65
|
-
from qgis.core import QgsFeature, QgsGeometry, QgsPointXY
|
|
66
|
-
|
|
67
|
-
# 开启编辑
|
|
68
|
-
layer.startEditing()
|
|
69
|
-
|
|
70
|
-
# 添加要素
|
|
71
|
-
feat = QgsFeature(layer.fields())
|
|
72
|
-
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
|
|
73
|
-
feat.setAttributes([1, "北京"])
|
|
74
|
-
layer.addFeature(feat)
|
|
75
|
-
|
|
76
|
-
# 修改已有要素属性
|
|
77
|
-
layer.changeAttributeValue(feature_id, field_index, new_value)
|
|
78
|
-
|
|
79
|
-
# 修改几何
|
|
80
|
-
layer.changeGeometry(feature_id, new_geometry)
|
|
81
|
-
|
|
82
|
-
# 删除要素
|
|
83
|
-
layer.deleteFeature(feature_id)
|
|
84
|
-
|
|
85
|
-
# 提交修改
|
|
86
|
-
layer.commitChanges()
|
|
87
|
-
# 或回滚
|
|
88
|
-
# layer.rollBack()
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 创建矢量文件
|
|
92
|
-
|
|
93
|
-
```python
|
|
94
|
-
from qgis.core import (
|
|
95
|
-
QgsVectorFileWriter, QgsVectorLayer, QgsFeature,
|
|
96
|
-
QgsGeometry, QgsPointXY, QgsField, QgsFields,
|
|
97
|
-
QgsCoordinateReferenceSystem, QgsWkbTypes
|
|
98
|
-
)
|
|
99
|
-
from qgis.PyQt.QtCore import QVariant
|
|
100
|
-
|
|
101
|
-
# 定义字段
|
|
102
|
-
fields = QgsFields()
|
|
103
|
-
fields.append(QgsField("id", QVariant.Int))
|
|
104
|
-
fields.append(QgsField("name", QVariant.String))
|
|
105
|
-
|
|
106
|
-
# 创建写入器
|
|
107
|
-
crs = QgsCoordinateReferenceSystem("EPSG:4326")
|
|
108
|
-
writer = QgsVectorFileWriter(
|
|
109
|
-
"/data/output.shp",
|
|
110
|
-
"UTF-8",
|
|
111
|
-
fields,
|
|
112
|
-
QgsWkbTypes.Point,
|
|
113
|
-
crs,
|
|
114
|
-
"ESRI Shapefile"
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
# 写入要素
|
|
118
|
-
feat = QgsFeature()
|
|
119
|
-
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
|
|
120
|
-
feat.setAttributes([1, "北京"])
|
|
121
|
-
writer.addFeature(feat)
|
|
122
|
-
|
|
123
|
-
del writer # 关闭文件
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 使用 SaveVectorOptions 写出(推荐)
|
|
127
|
-
|
|
128
|
-
```python
|
|
129
|
-
from qgis.core import QgsVectorFileWriter
|
|
130
|
-
|
|
131
|
-
options = QgsVectorFileWriter.SaveVectorOptions()
|
|
132
|
-
options.driverName = "GPKG"
|
|
133
|
-
options.fileEncoding = "UTF-8"
|
|
134
|
-
|
|
135
|
-
error = QgsVectorFileWriter.writeAsVectorFormatV3(
|
|
136
|
-
layer,
|
|
137
|
-
"/data/output.gpkg",
|
|
138
|
-
QgsProject.instance().transformContext(),
|
|
139
|
-
options
|
|
140
|
-
)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### 空间索引
|
|
144
|
-
|
|
145
|
-
```python
|
|
146
|
-
from qgis.core import QgsSpatialIndex
|
|
147
|
-
|
|
148
|
-
# 构建索引
|
|
149
|
-
index = QgsSpatialIndex(layer.getFeatures())
|
|
150
|
-
|
|
151
|
-
# 最近邻查询(返回要素 ID 列表)
|
|
152
|
-
nearest_ids = index.nearestNeighbor(QgsPointXY(116.4, 39.9), 5)
|
|
153
|
-
|
|
154
|
-
# 矩形范围查询
|
|
155
|
-
ids_in_rect = index.intersects(QgsRectangle(116.0, 39.0, 117.0, 40.0))
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 栅格图层操作
|
|
161
|
-
|
|
162
|
-
### 加载栅格图层
|
|
163
|
-
|
|
164
|
-
```python
|
|
165
|
-
from qgis.core import QgsRasterLayer
|
|
166
|
-
|
|
167
|
-
# 从文件加载
|
|
168
|
-
layer = QgsRasterLayer("/data/dem.tif", "DEM")
|
|
169
|
-
|
|
170
|
-
# WMS 服务
|
|
171
|
-
uri = "url=https://example.com/wms&layers=elevation&crs=EPSG:4326&format=image/png"
|
|
172
|
-
layer = QgsRasterLayer(uri, "WMS Layer", "wms")
|
|
173
|
-
|
|
174
|
-
if not layer.isValid():
|
|
175
|
-
print("栅格加载失败!")
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### 查询栅格值
|
|
179
|
-
|
|
180
|
-
```python
|
|
181
|
-
from qgis.core import QgsPointXY, QgsRaster
|
|
182
|
-
|
|
183
|
-
# 在指定坐标获取栅格值
|
|
184
|
-
point = QgsPointXY(116.4, 39.9)
|
|
185
|
-
result = layer.dataProvider().identify(point, QgsRaster.IdentifyFormatValue)
|
|
186
|
-
if result.isValid():
|
|
187
|
-
values = result.results() # {band_number: value}
|
|
188
|
-
print(values)
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### 栅格统计
|
|
192
|
-
|
|
193
|
-
```python
|
|
194
|
-
from qgis.core import QgsRasterBandStats
|
|
195
|
-
|
|
196
|
-
stats = layer.dataProvider().bandStatistics(1, QgsRasterBandStats.All)
|
|
197
|
-
print(f"最小值: {stats.minimumValue}")
|
|
198
|
-
print(f"最大值: {stats.maximumValue}")
|
|
199
|
-
print(f"平均值: {stats.mean}")
|
|
200
|
-
print(f"标准差: {stats.stdDev}")
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## 几何操作
|
|
206
|
-
|
|
207
|
-
### 创建几何
|
|
208
|
-
|
|
209
|
-
```python
|
|
210
|
-
from qgis.core import QgsGeometry, QgsPointXY, QgsPoint
|
|
211
|
-
|
|
212
|
-
# 点
|
|
213
|
-
geom_pt = QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9))
|
|
214
|
-
|
|
215
|
-
# 折线
|
|
216
|
-
geom_line = QgsGeometry.fromPolylineXY([
|
|
217
|
-
QgsPointXY(0, 0), QgsPointXY(10, 10), QgsPointXY(20, 0)
|
|
218
|
-
])
|
|
219
|
-
|
|
220
|
-
# 面
|
|
221
|
-
geom_poly = QgsGeometry.fromPolygonXY([[
|
|
222
|
-
QgsPointXY(0, 0), QgsPointXY(10, 0),
|
|
223
|
-
QgsPointXY(10, 10), QgsPointXY(0, 10),
|
|
224
|
-
QgsPointXY(0, 0)
|
|
225
|
-
]])
|
|
226
|
-
|
|
227
|
-
# 从 WKT 创建
|
|
228
|
-
geom = QgsGeometry.fromWkt("POINT(116.4 39.9)")
|
|
229
|
-
|
|
230
|
-
# 从 WKB 创建
|
|
231
|
-
geom = QgsGeometry()
|
|
232
|
-
geom.fromWkb(wkb_bytes)
|
|
233
|
-
|
|
234
|
-
# 从 GeoJSON 创建(通过 QgsJsonUtils)
|
|
235
|
-
from qgis.core import QgsJsonUtils
|
|
236
|
-
features = QgsJsonUtils.stringToFeatureList(geojson_string)
|
|
237
|
-
if features:
|
|
238
|
-
geom = features[0].geometry()
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 格式导出
|
|
242
|
-
|
|
243
|
-
```python
|
|
244
|
-
wkt = geom.asWkt() # WKT 字符串
|
|
245
|
-
wkb = geom.asWkb() # WKB bytes
|
|
246
|
-
json_str = geom.asJson() # GeoJSON 字符串
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### 空间运算
|
|
250
|
-
|
|
251
|
-
```python
|
|
252
|
-
# 缓冲区
|
|
253
|
-
buffered = geom.buffer(100, 16)
|
|
254
|
-
|
|
255
|
-
# 交集
|
|
256
|
-
intersection = geom1.intersection(geom2)
|
|
257
|
-
|
|
258
|
-
# 合并
|
|
259
|
-
union = geom1.combine(geom2)
|
|
260
|
-
|
|
261
|
-
# 差集
|
|
262
|
-
difference = geom1.difference(geom2)
|
|
263
|
-
|
|
264
|
-
# 对称差
|
|
265
|
-
sym_diff = geom1.symDifference(geom2)
|
|
266
|
-
|
|
267
|
-
# 凸包
|
|
268
|
-
hull = geom.convexHull()
|
|
269
|
-
|
|
270
|
-
# 质心
|
|
271
|
-
centroid = geom.centroid()
|
|
272
|
-
|
|
273
|
-
# 包围盒
|
|
274
|
-
bbox = geom.boundingBox() # 返回 QgsRectangle
|
|
275
|
-
|
|
276
|
-
# 简化
|
|
277
|
-
simplified = geom.simplify(tolerance)
|
|
278
|
-
|
|
279
|
-
# 有效性检查
|
|
280
|
-
is_valid = geom.isGeosValid()
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### 空间关系判断
|
|
284
|
-
|
|
285
|
-
```python
|
|
286
|
-
geom1.intersects(geom2) # 是否相交
|
|
287
|
-
geom1.contains(geom2) # 是否包含
|
|
288
|
-
geom1.within(geom2) # 是否在内部
|
|
289
|
-
geom1.overlaps(geom2) # 是否重叠
|
|
290
|
-
geom1.touches(geom2) # 是否相切
|
|
291
|
-
geom1.crosses(geom2) # 是否交叉
|
|
292
|
-
geom1.disjoint(geom2) # 是否不相交
|
|
293
|
-
geom1.equals(geom2) # 是否相等
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
### 距离与面积计算
|
|
297
|
-
|
|
298
|
-
```python
|
|
299
|
-
# 平面距离
|
|
300
|
-
dist = geom1.distance(geom2)
|
|
301
|
-
|
|
302
|
-
# 椭球面距离和面积(精确计算)
|
|
303
|
-
from qgis.core import QgsDistanceArea, QgsCoordinateReferenceSystem
|
|
304
|
-
|
|
305
|
-
da = QgsDistanceArea()
|
|
306
|
-
da.setSourceCrs(QgsCoordinateReferenceSystem("EPSG:4326"),
|
|
307
|
-
QgsProject.instance().transformContext())
|
|
308
|
-
da.setEllipsoid("WGS84")
|
|
309
|
-
|
|
310
|
-
length = da.measureLength(line_geom)
|
|
311
|
-
area = da.measureArea(polygon_geom)
|
|
312
|
-
|
|
313
|
-
# 两点间大地测量距离
|
|
314
|
-
d = da.measureLine(QgsPointXY(116.4, 39.9), QgsPointXY(121.5, 31.2))
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
1
|
+
# PyQGIS Vector and Raster Layer Operations Reference
|
|
2
|
+
|
|
3
|
+
> 这是 [../SKILL.md](../SKILL.md) 的补充文件,收录矢量/栅格图层操作的完整 API 与示例。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 矢量图层操作
|
|
8
|
+
|
|
9
|
+
### 加载矢量图层
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from qgis.core import QgsVectorLayer
|
|
13
|
+
|
|
14
|
+
# 从文件加载
|
|
15
|
+
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
|
|
16
|
+
|
|
17
|
+
# 从 GeoPackage 加载指定图层
|
|
18
|
+
layer = QgsVectorLayer("/data/data.gpkg|layername=rivers", "rivers", "ogr")
|
|
19
|
+
|
|
20
|
+
# 从 PostGIS 加载
|
|
21
|
+
uri = 'dbname=\'gis\' host=localhost port=5432 user=\'postgres\' table="public"."parcels" (geom)'
|
|
22
|
+
layer = QgsVectorLayer(uri, "parcels", "postgres")
|
|
23
|
+
|
|
24
|
+
# 内存图层
|
|
25
|
+
layer = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer&field=name:string(50)", "temp", "memory")
|
|
26
|
+
|
|
27
|
+
# 验证
|
|
28
|
+
if not layer.isValid():
|
|
29
|
+
print("图层加载失败!")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 遍历要素
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
for feature in layer.getFeatures():
|
|
36
|
+
geom = feature.geometry()
|
|
37
|
+
attrs = feature.attributes()
|
|
38
|
+
print(feature.id(), geom.asWkt(), attrs)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 按条件查询要素
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from qgis.core import QgsFeatureRequest
|
|
45
|
+
|
|
46
|
+
# 按属性过滤
|
|
47
|
+
request = QgsFeatureRequest().setFilterExpression('"population" > 10000')
|
|
48
|
+
for feature in layer.getFeatures(request):
|
|
49
|
+
print(feature["name"], feature["population"])
|
|
50
|
+
|
|
51
|
+
# 按空间范围过滤
|
|
52
|
+
from qgis.core import QgsRectangle
|
|
53
|
+
rect = QgsRectangle(116.0, 39.0, 117.0, 40.0)
|
|
54
|
+
request = QgsFeatureRequest().setFilterRect(rect)
|
|
55
|
+
for feature in layer.getFeatures(request):
|
|
56
|
+
print(feature.id())
|
|
57
|
+
|
|
58
|
+
# 限制返回字段(提升性能)
|
|
59
|
+
request = QgsFeatureRequest().setSubsetOfAttributes(["name", "area"], layer.fields())
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 编辑要素
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from qgis.core import QgsFeature, QgsGeometry, QgsPointXY
|
|
66
|
+
|
|
67
|
+
# 开启编辑
|
|
68
|
+
layer.startEditing()
|
|
69
|
+
|
|
70
|
+
# 添加要素
|
|
71
|
+
feat = QgsFeature(layer.fields())
|
|
72
|
+
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
|
|
73
|
+
feat.setAttributes([1, "北京"])
|
|
74
|
+
layer.addFeature(feat)
|
|
75
|
+
|
|
76
|
+
# 修改已有要素属性
|
|
77
|
+
layer.changeAttributeValue(feature_id, field_index, new_value)
|
|
78
|
+
|
|
79
|
+
# 修改几何
|
|
80
|
+
layer.changeGeometry(feature_id, new_geometry)
|
|
81
|
+
|
|
82
|
+
# 删除要素
|
|
83
|
+
layer.deleteFeature(feature_id)
|
|
84
|
+
|
|
85
|
+
# 提交修改
|
|
86
|
+
layer.commitChanges()
|
|
87
|
+
# 或回滚
|
|
88
|
+
# layer.rollBack()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 创建矢量文件
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from qgis.core import (
|
|
95
|
+
QgsVectorFileWriter, QgsVectorLayer, QgsFeature,
|
|
96
|
+
QgsGeometry, QgsPointXY, QgsField, QgsFields,
|
|
97
|
+
QgsCoordinateReferenceSystem, QgsWkbTypes
|
|
98
|
+
)
|
|
99
|
+
from qgis.PyQt.QtCore import QVariant
|
|
100
|
+
|
|
101
|
+
# 定义字段
|
|
102
|
+
fields = QgsFields()
|
|
103
|
+
fields.append(QgsField("id", QVariant.Int))
|
|
104
|
+
fields.append(QgsField("name", QVariant.String))
|
|
105
|
+
|
|
106
|
+
# 创建写入器
|
|
107
|
+
crs = QgsCoordinateReferenceSystem("EPSG:4326")
|
|
108
|
+
writer = QgsVectorFileWriter(
|
|
109
|
+
"/data/output.shp",
|
|
110
|
+
"UTF-8",
|
|
111
|
+
fields,
|
|
112
|
+
QgsWkbTypes.Point,
|
|
113
|
+
crs,
|
|
114
|
+
"ESRI Shapefile"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# 写入要素
|
|
118
|
+
feat = QgsFeature()
|
|
119
|
+
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
|
|
120
|
+
feat.setAttributes([1, "北京"])
|
|
121
|
+
writer.addFeature(feat)
|
|
122
|
+
|
|
123
|
+
del writer # 关闭文件
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 使用 SaveVectorOptions 写出(推荐)
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from qgis.core import QgsVectorFileWriter
|
|
130
|
+
|
|
131
|
+
options = QgsVectorFileWriter.SaveVectorOptions()
|
|
132
|
+
options.driverName = "GPKG"
|
|
133
|
+
options.fileEncoding = "UTF-8"
|
|
134
|
+
|
|
135
|
+
error = QgsVectorFileWriter.writeAsVectorFormatV3(
|
|
136
|
+
layer,
|
|
137
|
+
"/data/output.gpkg",
|
|
138
|
+
QgsProject.instance().transformContext(),
|
|
139
|
+
options
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 空间索引
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from qgis.core import QgsSpatialIndex
|
|
147
|
+
|
|
148
|
+
# 构建索引
|
|
149
|
+
index = QgsSpatialIndex(layer.getFeatures())
|
|
150
|
+
|
|
151
|
+
# 最近邻查询(返回要素 ID 列表)
|
|
152
|
+
nearest_ids = index.nearestNeighbor(QgsPointXY(116.4, 39.9), 5)
|
|
153
|
+
|
|
154
|
+
# 矩形范围查询
|
|
155
|
+
ids_in_rect = index.intersects(QgsRectangle(116.0, 39.0, 117.0, 40.0))
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 栅格图层操作
|
|
161
|
+
|
|
162
|
+
### 加载栅格图层
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from qgis.core import QgsRasterLayer
|
|
166
|
+
|
|
167
|
+
# 从文件加载
|
|
168
|
+
layer = QgsRasterLayer("/data/dem.tif", "DEM")
|
|
169
|
+
|
|
170
|
+
# WMS 服务
|
|
171
|
+
uri = "url=https://example.com/wms&layers=elevation&crs=EPSG:4326&format=image/png"
|
|
172
|
+
layer = QgsRasterLayer(uri, "WMS Layer", "wms")
|
|
173
|
+
|
|
174
|
+
if not layer.isValid():
|
|
175
|
+
print("栅格加载失败!")
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 查询栅格值
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from qgis.core import QgsPointXY, QgsRaster
|
|
182
|
+
|
|
183
|
+
# 在指定坐标获取栅格值
|
|
184
|
+
point = QgsPointXY(116.4, 39.9)
|
|
185
|
+
result = layer.dataProvider().identify(point, QgsRaster.IdentifyFormatValue)
|
|
186
|
+
if result.isValid():
|
|
187
|
+
values = result.results() # {band_number: value}
|
|
188
|
+
print(values)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 栅格统计
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from qgis.core import QgsRasterBandStats
|
|
195
|
+
|
|
196
|
+
stats = layer.dataProvider().bandStatistics(1, QgsRasterBandStats.All)
|
|
197
|
+
print(f"最小值: {stats.minimumValue}")
|
|
198
|
+
print(f"最大值: {stats.maximumValue}")
|
|
199
|
+
print(f"平均值: {stats.mean}")
|
|
200
|
+
print(f"标准差: {stats.stdDev}")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 几何操作
|
|
206
|
+
|
|
207
|
+
### 创建几何
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from qgis.core import QgsGeometry, QgsPointXY, QgsPoint
|
|
211
|
+
|
|
212
|
+
# 点
|
|
213
|
+
geom_pt = QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9))
|
|
214
|
+
|
|
215
|
+
# 折线
|
|
216
|
+
geom_line = QgsGeometry.fromPolylineXY([
|
|
217
|
+
QgsPointXY(0, 0), QgsPointXY(10, 10), QgsPointXY(20, 0)
|
|
218
|
+
])
|
|
219
|
+
|
|
220
|
+
# 面
|
|
221
|
+
geom_poly = QgsGeometry.fromPolygonXY([[
|
|
222
|
+
QgsPointXY(0, 0), QgsPointXY(10, 0),
|
|
223
|
+
QgsPointXY(10, 10), QgsPointXY(0, 10),
|
|
224
|
+
QgsPointXY(0, 0)
|
|
225
|
+
]])
|
|
226
|
+
|
|
227
|
+
# 从 WKT 创建
|
|
228
|
+
geom = QgsGeometry.fromWkt("POINT(116.4 39.9)")
|
|
229
|
+
|
|
230
|
+
# 从 WKB 创建
|
|
231
|
+
geom = QgsGeometry()
|
|
232
|
+
geom.fromWkb(wkb_bytes)
|
|
233
|
+
|
|
234
|
+
# 从 GeoJSON 创建(通过 QgsJsonUtils)
|
|
235
|
+
from qgis.core import QgsJsonUtils
|
|
236
|
+
features = QgsJsonUtils.stringToFeatureList(geojson_string)
|
|
237
|
+
if features:
|
|
238
|
+
geom = features[0].geometry()
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 格式导出
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
wkt = geom.asWkt() # WKT 字符串
|
|
245
|
+
wkb = geom.asWkb() # WKB bytes
|
|
246
|
+
json_str = geom.asJson() # GeoJSON 字符串
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 空间运算
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
# 缓冲区
|
|
253
|
+
buffered = geom.buffer(100, 16)
|
|
254
|
+
|
|
255
|
+
# 交集
|
|
256
|
+
intersection = geom1.intersection(geom2)
|
|
257
|
+
|
|
258
|
+
# 合并
|
|
259
|
+
union = geom1.combine(geom2)
|
|
260
|
+
|
|
261
|
+
# 差集
|
|
262
|
+
difference = geom1.difference(geom2)
|
|
263
|
+
|
|
264
|
+
# 对称差
|
|
265
|
+
sym_diff = geom1.symDifference(geom2)
|
|
266
|
+
|
|
267
|
+
# 凸包
|
|
268
|
+
hull = geom.convexHull()
|
|
269
|
+
|
|
270
|
+
# 质心
|
|
271
|
+
centroid = geom.centroid()
|
|
272
|
+
|
|
273
|
+
# 包围盒
|
|
274
|
+
bbox = geom.boundingBox() # 返回 QgsRectangle
|
|
275
|
+
|
|
276
|
+
# 简化
|
|
277
|
+
simplified = geom.simplify(tolerance)
|
|
278
|
+
|
|
279
|
+
# 有效性检查
|
|
280
|
+
is_valid = geom.isGeosValid()
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### 空间关系判断
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
geom1.intersects(geom2) # 是否相交
|
|
287
|
+
geom1.contains(geom2) # 是否包含
|
|
288
|
+
geom1.within(geom2) # 是否在内部
|
|
289
|
+
geom1.overlaps(geom2) # 是否重叠
|
|
290
|
+
geom1.touches(geom2) # 是否相切
|
|
291
|
+
geom1.crosses(geom2) # 是否交叉
|
|
292
|
+
geom1.disjoint(geom2) # 是否不相交
|
|
293
|
+
geom1.equals(geom2) # 是否相等
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 距离与面积计算
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
# 平面距离
|
|
300
|
+
dist = geom1.distance(geom2)
|
|
301
|
+
|
|
302
|
+
# 椭球面距离和面积(精确计算)
|
|
303
|
+
from qgis.core import QgsDistanceArea, QgsCoordinateReferenceSystem
|
|
304
|
+
|
|
305
|
+
da = QgsDistanceArea()
|
|
306
|
+
da.setSourceCrs(QgsCoordinateReferenceSystem("EPSG:4326"),
|
|
307
|
+
QgsProject.instance().transformContext())
|
|
308
|
+
da.setEllipsoid("WGS84")
|
|
309
|
+
|
|
310
|
+
length = da.measureLength(line_geom)
|
|
311
|
+
area = da.measureArea(polygon_geom)
|
|
312
|
+
|
|
313
|
+
# 两点间大地测量距离
|
|
314
|
+
d = da.measureLine(QgsPointXY(116.4, 39.9), QgsPointXY(121.5, 31.2))
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|