GeoLibre 矢量分析实战:Buffer 缓冲、叠加与属性连接工作流,以及三种计算引擎的底层实现
【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre
本篇围绕 GeoLibre 的矢量处理工作流展开:先缓冲一个矢量图层,再与第二个图层做叠加或连接,最后将结果导出为云原生格式。读完本文,你能在Processing → GeoLibre Toolbox → Vector中独立完成这套流程,并理解三种引擎(Turf.js 客户端、GeoPandas Sidecar、Pyodide 浏览器内 Python)在源码层面如何保证结果一致,以及各自的适用边界。
工具在哪里:先分清 Processing 菜单里的两个工具箱
本教程使用Processing → GeoLibre Toolbox → Vector打开的对话框。GeoLibre 的 Processing 菜单中同时存在两个工具箱(详见 处理工具文档):
- 分隔符上方的Vector子菜单属于 Whitebox 目录的矢量分类(WASM 工具目录);
- 分隔符下方的GeoLibre Toolbox → Vector才是本教程所用的对话框,包含 Buffer、Clip、Spatial join 等内置工具,并提供引擎选择器。
两者不是重复项:前者是上千个 WASM 工具的目录,后者是为 GeoLibre 定制的小而精的对话框工具集。
第 1 步:加载输入数据
至少添加一个矢量图层(方法见 Adding Data)。做叠加操作时需要两个图层——例如一组点或线图层,以及一个用于裁剪的多边形图层。
从源码结构看,所有矢量工具都通过ProcessingContext中的layers按图层 id 解析输入:vector-tools.ts 中的requireFeatures会取出指定参数对应的图层 GeoJSON,若为空则记录Error: parameter "layer" has no GeoJSON features并中止。也就是说,工具的操作对象始终是“已经在地图上的图层”的 GeoJSON 表示,而不是文件路径。
第 2 步:对图层做 Buffer(缓冲)
操作路径:Processing → GeoLibre Toolbox → Vector → Buffer,参数如下:
- Input layer:选择输入图层(必填);
- Distance:缓冲距离,默认
1,min: 0,step: 0.1; - Units:
kilometers/meters/miles,默认kilometers; - Engine(引擎,三选一):
- Client (Turf.js):完全在浏览器中运行,无需任何配置;
- Sidecar (GeoPandas):在桌面端的 Python sidecar 上运行,支持投影感知的距离计算;
- Python (Pyodide):与 sidecar 运行同一份 GeoPandas 代码,但在浏览器内执行,无需安装 sidecar。运行时首次使用时下载一次(几十 MB,从 CDN 惰性获取),之后复用。
点击Run后,缓冲结果会作为新图层添加到地图上。
Buffer 的更多参数:Buffer side
除了上面三个参数,bufferTool 的定义中还包含Buffer side参数,默认outside:
| 取值 | 行为 |
|---|---|
outside | 向外扩张(历史默认行为) |
inside | 向内收缩(用负半径缓冲实现;点/线没有内部区域,输入必须是多边形) |
both | 只保留边界两侧各distance范围内的条带 |
客户端实现见 bufferOneFeature:inside用buffer(feature, -radius);both则先求外扩几何与内缩几何的difference,得到真正的“环带”,并显式恢复源要素的属性。
投影感知的距离:为什么 GeoPandas 引擎更精确
!!! tip 客户端引擎在地理坐标系(经纬度)中直接缓冲。大范围区域的精确米制距离应使用两个 GeoPandas 引擎之一,它们会先重投影再缓冲:桌面端选Sidecar (GeoPandas),Web 构建或任何环境选Python (Pyodide)。
源码印证了这一点。Python 侧的 _buffer 流程是:
- 把距离按单位换算成米(
kilometers×1000、miles×1609.344); - 调用 _estimate_metric_crs 用
estimate_utm_crs()估算一个本地 UTM 坐标系,把数据重投影进去; - 在 UTM 米制空间执行
buffer(meters); - 结果再转回 WGS84 序列化。
该函数还内建国际日期变更线保护:若图层的经度跨度超过 180°,说明可能跨越日期变更线,此时estimate_utm_crs会选到错误时区导致结果严重失真,于是直接抛出可读错误,提示先按半球拆分几何或显式重投影。
另外客户端引擎也有一个容易被忽略的细节:Turf 的buffer内置的是地球半径,而 GeoLibre 支持月球/火星等行星项目,因此 bufferTool 在调用前会用bodyLengthToEarth(distance)把当前天体表面距离换算成“等效地球地面距离”,在地球上则为无操作。
双引擎一致性:同一参数的校验顺序
从源码结构看,客户端与 Python 引擎对同一组错误参数按相同顺序报告同一个首条错误:units→side→distance有限性 →distance符号。例如客户端用DECIMAL_NUMBER正则(vector-tools.ts L224)刻意只接受 Pythonfloat()也接受的十进制/科学计数法字符串,拒绝"0x10"、纯空白等;负距离两边都拒绝,因为“向内”由side表达。这保证了无论选哪个引擎,同一输入要么成功且结果一致,要么失败且报错一致。
第 3 步:叠加两个图层
用 Buffer 结果(或任意多边形图层)作为输入,与第二个图层做以下操作之一。在Processing → GeoLibre Toolbox → Vector中选择工具,指定输入层与叠加层,点击Run:
- Clip:保留输入图层落在叠加层内部的部分,并保留输入的属性。实现上(clipTool)客户端先把叠加层合并为单一几何,再对每个输入要素做
intersect,只保留输入属性(keepProperties: true)。 - Intersection:只保留两个多边形图层相互重叠的区域。与 Clip 不同,它合并两个图层的属性(intersectionTool 对每一对要素做交集并把双方
properties展开合并),对应 GeoPandas 的gpd.overlay(how="intersection")。 - Difference:从输入中挖掉叠加层覆盖的区域,保留输入属性。Python 侧用
gpd.overlay(..., how="difference", keep_geom_type=True)(vector_ops.py L291-L307)丢弃共享边界上产生的退化细条(线/点),符合 GIS 惯例。 - Union:把两个多边形图层合并成一个组合几何(两种引擎都不保留属性——unionTool 直接输出
properties: {})。 - Spatial join:基于空间关系(
intersects/within/contains)把连接层属性附加到每个输入要素上——例如给每个点打上包含它的那个多边形的属性。适用于任何几何类型。客户端实现(spatialJoinTool)与 GeoPandassjoin(predicate=..., how=...)语义对齐:关系按“输入 → 连接层”方向读;left连接为未匹配行用null填充所有连接层字段,保持输出 schema 一致;每个匹配生成一行输出。 - Attribute join:按关键字段匹配,把连接表属性附加到输入要素上,完全不涉及几何——例如用共同 FIPS 编码把人口普查统计连到边界多边形上。它是一对一的(首个匹配行胜出);需分别在两侧选择 key 字段,可选填要带过来的字段列表(留空则带过除 key 外的全部连接字段),并选择 inner 或 left 连接。客户端与 Python 侧共用同一套 key 归一化规则(
layerJoinKey/_attribute_join_key):空值永不匹配,数字5与字符串"5"可互相匹配,而补零编码"01001"只匹配完全相同字符串。
客户端成对运算的规模上限
Intersection、Spatial join、Select by location 这类两图层成对循环在主线程上执行,vector-tools.ts L52 定义了MAX_CLIENT_PAIRS = 250_000:当输入要素数 × 叠加要素数超过该上限时,客户端会明确报错并提示“use the Sidecar engine for large layers”,避免冻结浏览器标签页。对应的 Python 侧则用MAX_FEATURES = 50_000的输入要素上限(vector_ops.py L28)防止 sidecar 事件循环被阻塞,超限映射为 HTTP 413。
第 4 步:检查与微调
对结果图层打开 属性表 检查输出,并调整其 样式 使其与输入图层区分开。每次运行还会被记录到Processing → History:可一键重跑该条目,也可以复制等价的 Python 代码。两个工具箱(含快捷分析)共用同一份 History。
从源码结构看,结果回写统一走ctx.addResultLayer?.(名称, FeatureCollection)——这是工具产生输出到地图的唯一入口,也是 runner 在 Batch/Model 流水线中捕获中间结果的挂钩点:批量运行时把addResultLayer换成内存捕获,前一步的输出就以合成图层身份注入给下一步。
第 5 步:导出结果
要把输出保存为云原生文件,使用Processing → GeoLibre Toolbox → Conversion(例如Vector to GeoParquet或Vector to FlatGeobuf),详见 Cloud-Native Data。也可以从 属性表 或 SQL 工作区 导出记录。
Conversion 工具全部具备浏览器端引擎:Web 构建在 WASM 中写出 GeoJSON、CSV、GeoParquet、GeoPackage、FlatGeobuf、Shapefile(格式映射见 wasm-client.ts L27-L28);桌面端改由 Python sidecar 执行,可读写原生文件路径并覆盖 GDAL 支持的全部格式。
引擎架构:一套代码,三处执行
三种引擎并非三份实现:
- Client (Turf.js):packages/processing/src/vector-tools.ts 中每个工具对象的
run函数,操作图层 GeoJSON,可离线、可在移动端运行; - Sidecar (GeoPandas)与Python (Pyodide):vector_ops.py 的模块文档明确说明它是唯一的实现源头,不依赖 FastAPI——桌面端 sidecar 的
app/vector.py只是包装run_vector_tool并映射异常到 HTTP 状态码,而浏览器里 Pyodide 直接加载同一份源码调用它。GeoPandas/Shapely 负责几何,_DISPATCH表(L1192)把buffer、clip、spatial-join、attribute-join等工具 id 分发到对应处理函数。
这套“单一实现、双宿主”设计正是“Python (Pyodide) 引擎结果与 Sidecar 一致”这句话的底层保证。若 sidecar 未安装可选的vector依赖,对话框会自动回退到客户端引擎。
下一步
- 用 SQL 做同类分析:Spatial SQL;
- 转向栅格分析:Terrain Analysis;
- 完整工具清单与 Whitebox 工具箱说明见 Processing 文档。
【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考