@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,324 +1,324 @@
|
|
|
1
|
-
# OpenGIS Workflow Examples and Cheatsheets
|
|
2
|
-
|
|
3
|
-
End-to-end workflow examples, built-in algorithm cheatsheet, GDAL CLI cheatsheet, data formats and env vars split from SKILL.md.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 端到端工作流示例
|
|
8
|
-
|
|
9
|
-
### 示例 1:从 Shapefile 到地图服务(全自动)
|
|
10
|
-
|
|
11
|
-
完整流程:数据检查 → 重投影 → 缓冲区分析 → 发布到 GeoServer
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
#!/bin/bash
|
|
15
|
-
# === 阶段一:数据检查 ===
|
|
16
|
-
echo "=== 检查输入数据 ==="
|
|
17
|
-
ogrinfo -json buildings.shp | jq '.layers[0].featureCount'
|
|
18
|
-
|
|
19
|
-
# === 阶段二:数据处理 ===
|
|
20
|
-
echo "=== 重投影到 EPSG:4326 ==="
|
|
21
|
-
ogr2ogr -t_srs EPSG:4326 -f GPKG buildings_4326.gpkg buildings.shp
|
|
22
|
-
|
|
23
|
-
# === 阶段三:空间分析 ===
|
|
24
|
-
echo "=== 缓冲区分析(50米) ==="
|
|
25
|
-
qgis_process run native:buffer --json -- \
|
|
26
|
-
INPUT=buildings_4326.gpkg DISTANCE=50 SEGMENTS=16 OUTPUT=buildings_buffer.gpkg
|
|
27
|
-
|
|
28
|
-
echo "=== 融合 ==="
|
|
29
|
-
qgis_process run native:dissolve --json -- \
|
|
30
|
-
INPUT=buildings_buffer.gpkg OUTPUT=buildings_dissolved.gpkg
|
|
31
|
-
|
|
32
|
-
# === 阶段四:发布到 GeoServer ===
|
|
33
|
-
GEOSERVER="http://localhost:8080/geoserver"
|
|
34
|
-
AUTH="admin:geoserver"
|
|
35
|
-
|
|
36
|
-
echo "=== 创建工作空间 ==="
|
|
37
|
-
curl -u $AUTH -XPOST \
|
|
38
|
-
-H "Content-Type: application/json" \
|
|
39
|
-
-d '{"workspace":{"name":"analysis"}}' \
|
|
40
|
-
"$GEOSERVER/rest/workspaces"
|
|
41
|
-
|
|
42
|
-
echo "=== 上传并发布图层 ==="
|
|
43
|
-
# 将 GeoPackage 转换为 Shapefile ZIP 以便上传
|
|
44
|
-
ogr2ogr buildings_result.shp buildings_dissolved.gpkg
|
|
45
|
-
zip buildings_result.zip buildings_result.*
|
|
46
|
-
|
|
47
|
-
curl -u $AUTH -XPUT \
|
|
48
|
-
-H "Content-Type: application/zip" \
|
|
49
|
-
--data-binary @buildings_result.zip \
|
|
50
|
-
"$GEOSERVER/rest/workspaces/analysis/datastores/buildings/file.shp"
|
|
51
|
-
|
|
52
|
-
echo "=== 完成!==="
|
|
53
|
-
echo "WMS 地址: $GEOSERVER/wms?service=WMS&version=1.1.1&request=GetMap&layers=analysis:buildings_result&bbox=..."
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 示例 2:DEM 处理到坡度图服务(Python 全流程)
|
|
57
|
-
|
|
58
|
-
```python
|
|
59
|
-
"""从 DEM 生成坡度分析并发布到 GeoServer"""
|
|
60
|
-
import subprocess
|
|
61
|
-
import requests
|
|
62
|
-
from requests.auth import HTTPBasicAuth
|
|
63
|
-
|
|
64
|
-
GEOSERVER = "http://localhost:8080/geoserver"
|
|
65
|
-
AUTH = HTTPBasicAuth("admin", "geoserver")
|
|
66
|
-
|
|
67
|
-
# === 阶段一:数据检查 ===
|
|
68
|
-
subprocess.run(["gdalinfo", "dem.tif"], check=True)
|
|
69
|
-
|
|
70
|
-
# === 阶段二:数据处理 — 裁剪并重投影 ===
|
|
71
|
-
subprocess.run([
|
|
72
|
-
"gdalwarp", "-t_srs", "EPSG:4326",
|
|
73
|
-
"-cutline", "boundary.shp", "-crop_to_cutline",
|
|
74
|
-
"dem.tif", "dem_clipped.tif"
|
|
75
|
-
], check=True)
|
|
76
|
-
|
|
77
|
-
# === 阶段三:空间分析 — 坡度分析 ===
|
|
78
|
-
subprocess.run([
|
|
79
|
-
"qgis_process", "run", "gdal:slope", "--",
|
|
80
|
-
"INPUT=dem_clipped.tif", "OUTPUT=slope.tif"
|
|
81
|
-
], check=True)
|
|
82
|
-
|
|
83
|
-
# === 阶段四:发布到 GeoServer ===
|
|
84
|
-
# 创建工作空间
|
|
85
|
-
requests.post(
|
|
86
|
-
f"{GEOSERVER}/rest/workspaces",
|
|
87
|
-
json={"workspace": {"name": "terrain"}},
|
|
88
|
-
auth=AUTH
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# 上传坡度栅格
|
|
92
|
-
with open("slope.tif", "rb") as f:
|
|
93
|
-
requests.put(
|
|
94
|
-
f"{GEOSERVER}/rest/workspaces/terrain/coveragestores/slope/file.geotiff",
|
|
95
|
-
data=f,
|
|
96
|
-
headers={"Content-Type": "image/tiff"},
|
|
97
|
-
auth=AUTH
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
print("坡度图层已发布!")
|
|
101
|
-
print(f"WMS: {GEOSERVER}/wms?service=WMS&version=1.1.1&request=GetMap&layers=terrain:slope")
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 示例 3:PyQGIS 完整分析流程
|
|
105
|
-
|
|
106
|
-
```python
|
|
107
|
-
"""PyQGIS 独立脚本:加载数据 → 分析 → 导出 → 发布"""
|
|
108
|
-
import sys
|
|
109
|
-
import requests
|
|
110
|
-
from requests.auth import HTTPBasicAuth
|
|
111
|
-
from qgis.core import QgsApplication, QgsVectorLayer, QgsProject
|
|
112
|
-
import processing
|
|
113
|
-
from processing.core.Processing import Processing
|
|
114
|
-
|
|
115
|
-
# 初始化 QGIS
|
|
116
|
-
qgs = QgsApplication([], False)
|
|
117
|
-
qgs.setPrefixPath("/usr", True)
|
|
118
|
-
qgs.initQgis()
|
|
119
|
-
Processing.initialize()
|
|
120
|
-
|
|
121
|
-
# === 阶段一:加载数据 ===
|
|
122
|
-
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
|
|
123
|
-
assert layer.isValid(), "图层加载失败"
|
|
124
|
-
print(f"加载完成: {layer.featureCount()} 个要素")
|
|
125
|
-
|
|
126
|
-
# === 阶段二:重投影 ===
|
|
127
|
-
result1 = processing.run("native:reprojectlayer", {
|
|
128
|
-
'INPUT': layer,
|
|
129
|
-
'TARGET_CRS': 'EPSG:4326',
|
|
130
|
-
'OUTPUT': 'memory:reprojected'
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
# === 阶段三:缓冲区 + 融合 ===
|
|
134
|
-
result2 = processing.run("native:buffer", {
|
|
135
|
-
'INPUT': result1['OUTPUT'],
|
|
136
|
-
'DISTANCE': 100,
|
|
137
|
-
'SEGMENTS': 16,
|
|
138
|
-
'OUTPUT': 'memory:buffered'
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
result3 = processing.run("native:dissolve", {
|
|
142
|
-
'INPUT': result2['OUTPUT'],
|
|
143
|
-
'OUTPUT': '/data/buildings_analysis.gpkg'
|
|
144
|
-
})
|
|
145
|
-
print(f"分析完成: {result3['OUTPUT']}")
|
|
146
|
-
|
|
147
|
-
# === 阶段四:发布到 GeoServer ===
|
|
148
|
-
GEOSERVER = "http://localhost:8080/geoserver"
|
|
149
|
-
AUTH = HTTPBasicAuth("admin", "geoserver")
|
|
150
|
-
|
|
151
|
-
# 转换为 Shapefile ZIP 以上传
|
|
152
|
-
processing.run("native:reprojectlayer", {
|
|
153
|
-
'INPUT': result3['OUTPUT'],
|
|
154
|
-
'TARGET_CRS': 'EPSG:4326',
|
|
155
|
-
'OUTPUT': '/data/for_upload.shp'
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
import zipfile, glob
|
|
159
|
-
with zipfile.ZipFile("/data/for_upload.zip", "w") as zf:
|
|
160
|
-
for f in glob.glob("/data/for_upload.*"):
|
|
161
|
-
zf.write(f, f.split("/")[-1])
|
|
162
|
-
|
|
163
|
-
requests.post(f"{GEOSERVER}/rest/workspaces",
|
|
164
|
-
json={"workspace": {"name": "analysis"}}, auth=AUTH)
|
|
165
|
-
|
|
166
|
-
with open("/data/for_upload.zip", "rb") as f:
|
|
167
|
-
requests.put(
|
|
168
|
-
f"{GEOSERVER}/rest/workspaces/analysis/datastores/buildings/file.shp",
|
|
169
|
-
data=f, headers={"Content-Type": "application/zip"}, auth=AUTH
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
print("图层已发布到 GeoServer!")
|
|
173
|
-
|
|
174
|
-
qgs.exitQgis()
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### 示例 4:使用 qgis_process JSON 模式的自动化流水线
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
#!/bin/bash
|
|
181
|
-
# 适用于 CI/CD 自动化流水线
|
|
182
|
-
export QT_QPA_PLATFORM=offscreen
|
|
183
|
-
|
|
184
|
-
# 步骤 1:缓冲区分析(JSON 输入)
|
|
185
|
-
echo '{
|
|
186
|
-
"inputs": {
|
|
187
|
-
"INPUT": "/data/roads.shp",
|
|
188
|
-
"DISTANCE": 50,
|
|
189
|
-
"SEGMENTS": 10,
|
|
190
|
-
"OUTPUT": "/data/roads_buffer.gpkg"
|
|
191
|
-
}
|
|
192
|
-
}' | qgis_process run native:buffer -
|
|
193
|
-
|
|
194
|
-
# 步骤 2:解析输出路径
|
|
195
|
-
BUFFER_OUTPUT=$(echo '{
|
|
196
|
-
"inputs": {
|
|
197
|
-
"INPUT": "/data/roads.shp",
|
|
198
|
-
"DISTANCE": 50,
|
|
199
|
-
"SEGMENTS": 10,
|
|
200
|
-
"OUTPUT": "/data/roads_buffer.gpkg"
|
|
201
|
-
}
|
|
202
|
-
}' | qgis_process run native:buffer - | jq -r '.results.OUTPUT')
|
|
203
|
-
|
|
204
|
-
# 步骤 3:融合
|
|
205
|
-
qgis_process run native:dissolve --json -- \
|
|
206
|
-
INPUT="$BUFFER_OUTPUT" OUTPUT=/data/roads_dissolved.gpkg
|
|
207
|
-
|
|
208
|
-
# 步骤 4:发布到 GeoServer
|
|
209
|
-
ogr2ogr roads_final.shp /data/roads_dissolved.gpkg
|
|
210
|
-
zip roads_final.zip roads_final.*
|
|
211
|
-
|
|
212
|
-
curl -u admin:geoserver -XPUT \
|
|
213
|
-
-H "Content-Type: application/zip" \
|
|
214
|
-
--data-binary @roads_final.zip \
|
|
215
|
-
"http://localhost:8080/geoserver/rest/workspaces/myws/datastores/roads/file.shp"
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## 常用内置算法速查(qgis_process / PyQGIS)
|
|
221
|
-
|
|
222
|
-
### 矢量分析
|
|
223
|
-
|
|
224
|
-
| 算法 ID | 说明 | 关键参数 |
|
|
225
|
-
|---------|------|---------|
|
|
226
|
-
| `native:buffer` | 缓冲区分析 | INPUT, DISTANCE, SEGMENTS, DISSOLVE |
|
|
227
|
-
| `native:clip` | 矢量裁剪 | INPUT, OVERLAY |
|
|
228
|
-
| `native:dissolve` | 融合 | INPUT, FIELD |
|
|
229
|
-
| `native:intersection` | 交集 | INPUT, OVERLAY |
|
|
230
|
-
| `native:union` | 联合 | INPUT, OVERLAY |
|
|
231
|
-
| `native:difference` | 差集 | INPUT, OVERLAY |
|
|
232
|
-
| `native:symmetricaldifference` | 对称差 | INPUT, OVERLAY |
|
|
233
|
-
| `native:centroids` | 质心 | INPUT |
|
|
234
|
-
| `native:convexhull` | 凸包 | INPUT |
|
|
235
|
-
| `native:simplifygeometries` | 简化几何 | INPUT, TOLERANCE |
|
|
236
|
-
| `native:reprojectlayer` | 重投影 | INPUT, TARGET_CRS |
|
|
237
|
-
| `native:mergevectorlayers` | 合并图层 | LAYERS |
|
|
238
|
-
| `native:splitvectorlayer` | 拆分图层 | INPUT, FIELD |
|
|
239
|
-
| `native:extractbyattribute` | 按属性提取 | INPUT, FIELD, OPERATOR, VALUE |
|
|
240
|
-
| `native:extractbylocation` | 按位置提取 | INPUT, INTERSECT, PREDICATE |
|
|
241
|
-
| `native:joinattributesbylocation` | 按位置连接属性 | INPUT, JOIN, PREDICATE |
|
|
242
|
-
| `native:fixgeometries` | 修复几何 | INPUT |
|
|
243
|
-
| `native:countpointsinpolygon` | 多边形内点计数 | POLYGONS, POINTS |
|
|
244
|
-
| `native:voronoipolygons` | 泰森多边形 | INPUT |
|
|
245
|
-
| `native:creategrid` | 创建网格 | TYPE, EXTENT, HSPACING, VSPACING |
|
|
246
|
-
| `native:fieldcalculator` | 字段计算器 | INPUT, FIELD_NAME, FORMULA |
|
|
247
|
-
|
|
248
|
-
### 栅格分析
|
|
249
|
-
|
|
250
|
-
| 算法 ID | 说明 | 关键参数 |
|
|
251
|
-
|---------|------|---------|
|
|
252
|
-
| `native:rasterlayerstatistics` | 栅格统计 | INPUT |
|
|
253
|
-
| `gdal:cliprasterbyextent` | 按范围裁剪栅格 | INPUT, EXTENT |
|
|
254
|
-
| `gdal:cliprasterbymask` | 按掩膜裁剪栅格 | INPUT, MASK |
|
|
255
|
-
| `gdal:merge` | 栅格合并 | INPUT |
|
|
256
|
-
| `gdal:warpreproject` | 栅格重投影 | INPUT, TARGET_CRS |
|
|
257
|
-
| `gdal:contour` | 等值线提取 | INPUT, INTERVAL |
|
|
258
|
-
| `gdal:polygonize` | 栅格转矢量 | INPUT |
|
|
259
|
-
| `gdal:rasterize` | 矢量转栅格 | INPUT, FIELD |
|
|
260
|
-
| `gdal:hillshade` | 山体阴影 | INPUT |
|
|
261
|
-
| `gdal:slope` | 坡度分析 | INPUT |
|
|
262
|
-
| `gdal:aspect` | 坡向分析 | INPUT |
|
|
263
|
-
| `gdal:roughness` | 粗糙度 | INPUT |
|
|
264
|
-
| `gdal:buildvirtualraster` | 构建虚拟栅格 | INPUT |
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## GDAL 命令行工具速查
|
|
269
|
-
|
|
270
|
-
### 矢量工具
|
|
271
|
-
|
|
272
|
-
| 命令 | 说明 |
|
|
273
|
-
|------|------|
|
|
274
|
-
| `ogrinfo` | 矢量数据信息查询 |
|
|
275
|
-
| `ogr2ogr` | 矢量格式转换和处理 |
|
|
276
|
-
|
|
277
|
-
### 栅格工具
|
|
278
|
-
|
|
279
|
-
| 命令 | 说明 |
|
|
280
|
-
|------|------|
|
|
281
|
-
| `gdalinfo` | 栅格数据信息查询 |
|
|
282
|
-
| `gdal_translate` | 栅格格式转换和重采样 |
|
|
283
|
-
| `gdalwarp` | 栅格重投影和镶嵌 |
|
|
284
|
-
| `gdal_merge.py` | 栅格镶嵌融合 |
|
|
285
|
-
| `gdal_calc.py` | 栅格计算器(NumPy 语法) |
|
|
286
|
-
| `gdal_contour` | 等值线提取 |
|
|
287
|
-
| `gdal_grid` | 散点数据插值创建网格 |
|
|
288
|
-
| `gdal_polygonize.py` | 栅格转矢量 |
|
|
289
|
-
| `gdaltindex` | 创建栅格瓦片索引 |
|
|
290
|
-
| `gdal_edit.py` | 编辑栅格元数据 |
|
|
291
|
-
| `nearblack` | 清理黑白边界 |
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
## 数据格式支持
|
|
296
|
-
|
|
297
|
-
### 矢量格式
|
|
298
|
-
|
|
299
|
-
| 格式 | 扩展名 | 说明 |
|
|
300
|
-
|------|--------|------|
|
|
301
|
-
| Shapefile | .shp | ESRI 标准格式 |
|
|
302
|
-
| GeoJSON | .geojson | Web 标准 JSON |
|
|
303
|
-
| GeoPackage | .gpkg | SQLite 基础,推荐 |
|
|
304
|
-
| KML | .kml | Google Maps 格式 |
|
|
305
|
-
| PostGIS | N/A | 数据库矢量存储 |
|
|
306
|
-
| GML | .gml | ISO 标准 XML |
|
|
307
|
-
| CSV | .csv | 点数据 |
|
|
308
|
-
| FlatGeobuf | .fgb | 高性能流式二进制格式 |
|
|
309
|
-
|
|
310
|
-
### 栅格格式
|
|
311
|
-
|
|
312
|
-
| 格式 | 扩展名 | 说明 |
|
|
313
|
-
|------|--------|------|
|
|
314
|
-
| GeoTIFF | .tif | 标准地理栅格(推荐) |
|
|
315
|
-
| COG | .tif | 云优化 GeoTIFF |
|
|
316
|
-
| PNG | .png | Web 图像 |
|
|
317
|
-
| JPEG | .jpg | 有损压缩 |
|
|
318
|
-
| NetCDF | .nc | 科学数据 |
|
|
319
|
-
| HDF5 | .h5 | 多维数据 |
|
|
320
|
-
| JPEG2000 | .jp2 | 高质量压缩 |
|
|
321
|
-
| ASCII Grid | .asc | 简单栅格 |
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
1
|
+
# OpenGIS Workflow Examples and Cheatsheets
|
|
2
|
+
|
|
3
|
+
End-to-end workflow examples, built-in algorithm cheatsheet, GDAL CLI cheatsheet, data formats and env vars split from SKILL.md.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 端到端工作流示例
|
|
8
|
+
|
|
9
|
+
### 示例 1:从 Shapefile 到地图服务(全自动)
|
|
10
|
+
|
|
11
|
+
完整流程:数据检查 → 重投影 → 缓冲区分析 → 发布到 GeoServer
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
#!/bin/bash
|
|
15
|
+
# === 阶段一:数据检查 ===
|
|
16
|
+
echo "=== 检查输入数据 ==="
|
|
17
|
+
ogrinfo -json buildings.shp | jq '.layers[0].featureCount'
|
|
18
|
+
|
|
19
|
+
# === 阶段二:数据处理 ===
|
|
20
|
+
echo "=== 重投影到 EPSG:4326 ==="
|
|
21
|
+
ogr2ogr -t_srs EPSG:4326 -f GPKG buildings_4326.gpkg buildings.shp
|
|
22
|
+
|
|
23
|
+
# === 阶段三:空间分析 ===
|
|
24
|
+
echo "=== 缓冲区分析(50米) ==="
|
|
25
|
+
qgis_process run native:buffer --json -- \
|
|
26
|
+
INPUT=buildings_4326.gpkg DISTANCE=50 SEGMENTS=16 OUTPUT=buildings_buffer.gpkg
|
|
27
|
+
|
|
28
|
+
echo "=== 融合 ==="
|
|
29
|
+
qgis_process run native:dissolve --json -- \
|
|
30
|
+
INPUT=buildings_buffer.gpkg OUTPUT=buildings_dissolved.gpkg
|
|
31
|
+
|
|
32
|
+
# === 阶段四:发布到 GeoServer ===
|
|
33
|
+
GEOSERVER="http://localhost:8080/geoserver"
|
|
34
|
+
AUTH="admin:geoserver"
|
|
35
|
+
|
|
36
|
+
echo "=== 创建工作空间 ==="
|
|
37
|
+
curl -u $AUTH -XPOST \
|
|
38
|
+
-H "Content-Type: application/json" \
|
|
39
|
+
-d '{"workspace":{"name":"analysis"}}' \
|
|
40
|
+
"$GEOSERVER/rest/workspaces"
|
|
41
|
+
|
|
42
|
+
echo "=== 上传并发布图层 ==="
|
|
43
|
+
# 将 GeoPackage 转换为 Shapefile ZIP 以便上传
|
|
44
|
+
ogr2ogr buildings_result.shp buildings_dissolved.gpkg
|
|
45
|
+
zip buildings_result.zip buildings_result.*
|
|
46
|
+
|
|
47
|
+
curl -u $AUTH -XPUT \
|
|
48
|
+
-H "Content-Type: application/zip" \
|
|
49
|
+
--data-binary @buildings_result.zip \
|
|
50
|
+
"$GEOSERVER/rest/workspaces/analysis/datastores/buildings/file.shp"
|
|
51
|
+
|
|
52
|
+
echo "=== 完成!==="
|
|
53
|
+
echo "WMS 地址: $GEOSERVER/wms?service=WMS&version=1.1.1&request=GetMap&layers=analysis:buildings_result&bbox=..."
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 示例 2:DEM 处理到坡度图服务(Python 全流程)
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
"""从 DEM 生成坡度分析并发布到 GeoServer"""
|
|
60
|
+
import subprocess
|
|
61
|
+
import requests
|
|
62
|
+
from requests.auth import HTTPBasicAuth
|
|
63
|
+
|
|
64
|
+
GEOSERVER = "http://localhost:8080/geoserver"
|
|
65
|
+
AUTH = HTTPBasicAuth("admin", "geoserver")
|
|
66
|
+
|
|
67
|
+
# === 阶段一:数据检查 ===
|
|
68
|
+
subprocess.run(["gdalinfo", "dem.tif"], check=True)
|
|
69
|
+
|
|
70
|
+
# === 阶段二:数据处理 — 裁剪并重投影 ===
|
|
71
|
+
subprocess.run([
|
|
72
|
+
"gdalwarp", "-t_srs", "EPSG:4326",
|
|
73
|
+
"-cutline", "boundary.shp", "-crop_to_cutline",
|
|
74
|
+
"dem.tif", "dem_clipped.tif"
|
|
75
|
+
], check=True)
|
|
76
|
+
|
|
77
|
+
# === 阶段三:空间分析 — 坡度分析 ===
|
|
78
|
+
subprocess.run([
|
|
79
|
+
"qgis_process", "run", "gdal:slope", "--",
|
|
80
|
+
"INPUT=dem_clipped.tif", "OUTPUT=slope.tif"
|
|
81
|
+
], check=True)
|
|
82
|
+
|
|
83
|
+
# === 阶段四:发布到 GeoServer ===
|
|
84
|
+
# 创建工作空间
|
|
85
|
+
requests.post(
|
|
86
|
+
f"{GEOSERVER}/rest/workspaces",
|
|
87
|
+
json={"workspace": {"name": "terrain"}},
|
|
88
|
+
auth=AUTH
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# 上传坡度栅格
|
|
92
|
+
with open("slope.tif", "rb") as f:
|
|
93
|
+
requests.put(
|
|
94
|
+
f"{GEOSERVER}/rest/workspaces/terrain/coveragestores/slope/file.geotiff",
|
|
95
|
+
data=f,
|
|
96
|
+
headers={"Content-Type": "image/tiff"},
|
|
97
|
+
auth=AUTH
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
print("坡度图层已发布!")
|
|
101
|
+
print(f"WMS: {GEOSERVER}/wms?service=WMS&version=1.1.1&request=GetMap&layers=terrain:slope")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 示例 3:PyQGIS 完整分析流程
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
"""PyQGIS 独立脚本:加载数据 → 分析 → 导出 → 发布"""
|
|
108
|
+
import sys
|
|
109
|
+
import requests
|
|
110
|
+
from requests.auth import HTTPBasicAuth
|
|
111
|
+
from qgis.core import QgsApplication, QgsVectorLayer, QgsProject
|
|
112
|
+
import processing
|
|
113
|
+
from processing.core.Processing import Processing
|
|
114
|
+
|
|
115
|
+
# 初始化 QGIS
|
|
116
|
+
qgs = QgsApplication([], False)
|
|
117
|
+
qgs.setPrefixPath("/usr", True)
|
|
118
|
+
qgs.initQgis()
|
|
119
|
+
Processing.initialize()
|
|
120
|
+
|
|
121
|
+
# === 阶段一:加载数据 ===
|
|
122
|
+
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
|
|
123
|
+
assert layer.isValid(), "图层加载失败"
|
|
124
|
+
print(f"加载完成: {layer.featureCount()} 个要素")
|
|
125
|
+
|
|
126
|
+
# === 阶段二:重投影 ===
|
|
127
|
+
result1 = processing.run("native:reprojectlayer", {
|
|
128
|
+
'INPUT': layer,
|
|
129
|
+
'TARGET_CRS': 'EPSG:4326',
|
|
130
|
+
'OUTPUT': 'memory:reprojected'
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
# === 阶段三:缓冲区 + 融合 ===
|
|
134
|
+
result2 = processing.run("native:buffer", {
|
|
135
|
+
'INPUT': result1['OUTPUT'],
|
|
136
|
+
'DISTANCE': 100,
|
|
137
|
+
'SEGMENTS': 16,
|
|
138
|
+
'OUTPUT': 'memory:buffered'
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
result3 = processing.run("native:dissolve", {
|
|
142
|
+
'INPUT': result2['OUTPUT'],
|
|
143
|
+
'OUTPUT': '/data/buildings_analysis.gpkg'
|
|
144
|
+
})
|
|
145
|
+
print(f"分析完成: {result3['OUTPUT']}")
|
|
146
|
+
|
|
147
|
+
# === 阶段四:发布到 GeoServer ===
|
|
148
|
+
GEOSERVER = "http://localhost:8080/geoserver"
|
|
149
|
+
AUTH = HTTPBasicAuth("admin", "geoserver")
|
|
150
|
+
|
|
151
|
+
# 转换为 Shapefile ZIP 以上传
|
|
152
|
+
processing.run("native:reprojectlayer", {
|
|
153
|
+
'INPUT': result3['OUTPUT'],
|
|
154
|
+
'TARGET_CRS': 'EPSG:4326',
|
|
155
|
+
'OUTPUT': '/data/for_upload.shp'
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
import zipfile, glob
|
|
159
|
+
with zipfile.ZipFile("/data/for_upload.zip", "w") as zf:
|
|
160
|
+
for f in glob.glob("/data/for_upload.*"):
|
|
161
|
+
zf.write(f, f.split("/")[-1])
|
|
162
|
+
|
|
163
|
+
requests.post(f"{GEOSERVER}/rest/workspaces",
|
|
164
|
+
json={"workspace": {"name": "analysis"}}, auth=AUTH)
|
|
165
|
+
|
|
166
|
+
with open("/data/for_upload.zip", "rb") as f:
|
|
167
|
+
requests.put(
|
|
168
|
+
f"{GEOSERVER}/rest/workspaces/analysis/datastores/buildings/file.shp",
|
|
169
|
+
data=f, headers={"Content-Type": "application/zip"}, auth=AUTH
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
print("图层已发布到 GeoServer!")
|
|
173
|
+
|
|
174
|
+
qgs.exitQgis()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 示例 4:使用 qgis_process JSON 模式的自动化流水线
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
#!/bin/bash
|
|
181
|
+
# 适用于 CI/CD 自动化流水线
|
|
182
|
+
export QT_QPA_PLATFORM=offscreen
|
|
183
|
+
|
|
184
|
+
# 步骤 1:缓冲区分析(JSON 输入)
|
|
185
|
+
echo '{
|
|
186
|
+
"inputs": {
|
|
187
|
+
"INPUT": "/data/roads.shp",
|
|
188
|
+
"DISTANCE": 50,
|
|
189
|
+
"SEGMENTS": 10,
|
|
190
|
+
"OUTPUT": "/data/roads_buffer.gpkg"
|
|
191
|
+
}
|
|
192
|
+
}' | qgis_process run native:buffer -
|
|
193
|
+
|
|
194
|
+
# 步骤 2:解析输出路径
|
|
195
|
+
BUFFER_OUTPUT=$(echo '{
|
|
196
|
+
"inputs": {
|
|
197
|
+
"INPUT": "/data/roads.shp",
|
|
198
|
+
"DISTANCE": 50,
|
|
199
|
+
"SEGMENTS": 10,
|
|
200
|
+
"OUTPUT": "/data/roads_buffer.gpkg"
|
|
201
|
+
}
|
|
202
|
+
}' | qgis_process run native:buffer - | jq -r '.results.OUTPUT')
|
|
203
|
+
|
|
204
|
+
# 步骤 3:融合
|
|
205
|
+
qgis_process run native:dissolve --json -- \
|
|
206
|
+
INPUT="$BUFFER_OUTPUT" OUTPUT=/data/roads_dissolved.gpkg
|
|
207
|
+
|
|
208
|
+
# 步骤 4:发布到 GeoServer
|
|
209
|
+
ogr2ogr roads_final.shp /data/roads_dissolved.gpkg
|
|
210
|
+
zip roads_final.zip roads_final.*
|
|
211
|
+
|
|
212
|
+
curl -u admin:geoserver -XPUT \
|
|
213
|
+
-H "Content-Type: application/zip" \
|
|
214
|
+
--data-binary @roads_final.zip \
|
|
215
|
+
"http://localhost:8080/geoserver/rest/workspaces/myws/datastores/roads/file.shp"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 常用内置算法速查(qgis_process / PyQGIS)
|
|
221
|
+
|
|
222
|
+
### 矢量分析
|
|
223
|
+
|
|
224
|
+
| 算法 ID | 说明 | 关键参数 |
|
|
225
|
+
|---------|------|---------|
|
|
226
|
+
| `native:buffer` | 缓冲区分析 | INPUT, DISTANCE, SEGMENTS, DISSOLVE |
|
|
227
|
+
| `native:clip` | 矢量裁剪 | INPUT, OVERLAY |
|
|
228
|
+
| `native:dissolve` | 融合 | INPUT, FIELD |
|
|
229
|
+
| `native:intersection` | 交集 | INPUT, OVERLAY |
|
|
230
|
+
| `native:union` | 联合 | INPUT, OVERLAY |
|
|
231
|
+
| `native:difference` | 差集 | INPUT, OVERLAY |
|
|
232
|
+
| `native:symmetricaldifference` | 对称差 | INPUT, OVERLAY |
|
|
233
|
+
| `native:centroids` | 质心 | INPUT |
|
|
234
|
+
| `native:convexhull` | 凸包 | INPUT |
|
|
235
|
+
| `native:simplifygeometries` | 简化几何 | INPUT, TOLERANCE |
|
|
236
|
+
| `native:reprojectlayer` | 重投影 | INPUT, TARGET_CRS |
|
|
237
|
+
| `native:mergevectorlayers` | 合并图层 | LAYERS |
|
|
238
|
+
| `native:splitvectorlayer` | 拆分图层 | INPUT, FIELD |
|
|
239
|
+
| `native:extractbyattribute` | 按属性提取 | INPUT, FIELD, OPERATOR, VALUE |
|
|
240
|
+
| `native:extractbylocation` | 按位置提取 | INPUT, INTERSECT, PREDICATE |
|
|
241
|
+
| `native:joinattributesbylocation` | 按位置连接属性 | INPUT, JOIN, PREDICATE |
|
|
242
|
+
| `native:fixgeometries` | 修复几何 | INPUT |
|
|
243
|
+
| `native:countpointsinpolygon` | 多边形内点计数 | POLYGONS, POINTS |
|
|
244
|
+
| `native:voronoipolygons` | 泰森多边形 | INPUT |
|
|
245
|
+
| `native:creategrid` | 创建网格 | TYPE, EXTENT, HSPACING, VSPACING |
|
|
246
|
+
| `native:fieldcalculator` | 字段计算器 | INPUT, FIELD_NAME, FORMULA |
|
|
247
|
+
|
|
248
|
+
### 栅格分析
|
|
249
|
+
|
|
250
|
+
| 算法 ID | 说明 | 关键参数 |
|
|
251
|
+
|---------|------|---------|
|
|
252
|
+
| `native:rasterlayerstatistics` | 栅格统计 | INPUT |
|
|
253
|
+
| `gdal:cliprasterbyextent` | 按范围裁剪栅格 | INPUT, EXTENT |
|
|
254
|
+
| `gdal:cliprasterbymask` | 按掩膜裁剪栅格 | INPUT, MASK |
|
|
255
|
+
| `gdal:merge` | 栅格合并 | INPUT |
|
|
256
|
+
| `gdal:warpreproject` | 栅格重投影 | INPUT, TARGET_CRS |
|
|
257
|
+
| `gdal:contour` | 等值线提取 | INPUT, INTERVAL |
|
|
258
|
+
| `gdal:polygonize` | 栅格转矢量 | INPUT |
|
|
259
|
+
| `gdal:rasterize` | 矢量转栅格 | INPUT, FIELD |
|
|
260
|
+
| `gdal:hillshade` | 山体阴影 | INPUT |
|
|
261
|
+
| `gdal:slope` | 坡度分析 | INPUT |
|
|
262
|
+
| `gdal:aspect` | 坡向分析 | INPUT |
|
|
263
|
+
| `gdal:roughness` | 粗糙度 | INPUT |
|
|
264
|
+
| `gdal:buildvirtualraster` | 构建虚拟栅格 | INPUT |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## GDAL 命令行工具速查
|
|
269
|
+
|
|
270
|
+
### 矢量工具
|
|
271
|
+
|
|
272
|
+
| 命令 | 说明 |
|
|
273
|
+
|------|------|
|
|
274
|
+
| `ogrinfo` | 矢量数据信息查询 |
|
|
275
|
+
| `ogr2ogr` | 矢量格式转换和处理 |
|
|
276
|
+
|
|
277
|
+
### 栅格工具
|
|
278
|
+
|
|
279
|
+
| 命令 | 说明 |
|
|
280
|
+
|------|------|
|
|
281
|
+
| `gdalinfo` | 栅格数据信息查询 |
|
|
282
|
+
| `gdal_translate` | 栅格格式转换和重采样 |
|
|
283
|
+
| `gdalwarp` | 栅格重投影和镶嵌 |
|
|
284
|
+
| `gdal_merge.py` | 栅格镶嵌融合 |
|
|
285
|
+
| `gdal_calc.py` | 栅格计算器(NumPy 语法) |
|
|
286
|
+
| `gdal_contour` | 等值线提取 |
|
|
287
|
+
| `gdal_grid` | 散点数据插值创建网格 |
|
|
288
|
+
| `gdal_polygonize.py` | 栅格转矢量 |
|
|
289
|
+
| `gdaltindex` | 创建栅格瓦片索引 |
|
|
290
|
+
| `gdal_edit.py` | 编辑栅格元数据 |
|
|
291
|
+
| `nearblack` | 清理黑白边界 |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 数据格式支持
|
|
296
|
+
|
|
297
|
+
### 矢量格式
|
|
298
|
+
|
|
299
|
+
| 格式 | 扩展名 | 说明 |
|
|
300
|
+
|------|--------|------|
|
|
301
|
+
| Shapefile | .shp | ESRI 标准格式 |
|
|
302
|
+
| GeoJSON | .geojson | Web 标准 JSON |
|
|
303
|
+
| GeoPackage | .gpkg | SQLite 基础,推荐 |
|
|
304
|
+
| KML | .kml | Google Maps 格式 |
|
|
305
|
+
| PostGIS | N/A | 数据库矢量存储 |
|
|
306
|
+
| GML | .gml | ISO 标准 XML |
|
|
307
|
+
| CSV | .csv | 点数据 |
|
|
308
|
+
| FlatGeobuf | .fgb | 高性能流式二进制格式 |
|
|
309
|
+
|
|
310
|
+
### 栅格格式
|
|
311
|
+
|
|
312
|
+
| 格式 | 扩展名 | 说明 |
|
|
313
|
+
|------|--------|------|
|
|
314
|
+
| GeoTIFF | .tif | 标准地理栅格(推荐) |
|
|
315
|
+
| COG | .tif | 云优化 GeoTIFF |
|
|
316
|
+
| PNG | .png | Web 图像 |
|
|
317
|
+
| JPEG | .jpg | 有损压缩 |
|
|
318
|
+
| NetCDF | .nc | 科学数据 |
|
|
319
|
+
| HDF5 | .h5 | 多维数据 |
|
|
320
|
+
| JPEG2000 | .jp2 | 高质量压缩 |
|
|
321
|
+
| ASCII Grid | .asc | 简单栅格 |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|