用Web Worker做GIS几何重叠计算,核心是将交集、并集、差集等CPU密集操作移出主线程,关键在数据轻量化传输、分块纯函数执行及结果适配渲染层。

用 Web Worker 做大规模 GIS 数据的几何重叠计算,核心是把“算交集、并集、差集”这类 CPU 密集型操作从主线程移出去,避免地图拖不动、按钮点没反应。这不是简单加个线程就能提速,关键在于数据怎么传、算法怎么写、结果怎么接。
哪些重叠计算适合扔进 Worker
不是所有空间运算都值得上 Worker。优先考虑以下几类:
- 多边形与多边形批量相交(比如统计某区域落在多个行政区内的面积)
- 点集对海量面图层的空间包含判断(如10万用户坐标是否在500个缓冲区内部)
- 线要素与面要素的裁剪或叠加(如道路穿过不同土地利用类型的分段统计)
- 基于容差的拓扑检查(如识别相邻地块间未闭合的缝隙或微小重叠)
数据必须轻量、可序列化、零拷贝传输
Worker 和主线程不共享内存,传大对象等于复制大对象——这是性能杀手。正确做法是只传原始数值数组:
- 把 GeoJSON 中的 coordinates 提取为一维 Float64Array(例如
[x1,y1,x2,y2,...]),用postMessage(arr, [arr.buffer])转移所有权 - 避免传整个 Feature 或 Geometry 对象;用紧凑结构描述:顶点数、环数、类型标识(1=Point, 2=LineString, 3=Polygon)、起始偏移索引表
- 若需参考坐标系或投影参数,只传必要字段(如 EPSG 编号、中央经线、比例尺因子),不传完整 Proj4 字符串或 CRS 对象
Worker 内部要纯函数 + 分块执行
不能依赖外部状态,也不能长期霸占线程。推荐按以下方式组织逻辑:
- 使用 Rust/TypeScript 编写的轻量几何库(如 robust-predicates 或 martinez 的 wasm 封装),避免 JS 浮点误差导致拓扑失败
- 对大批量目标做分片处理:每次最多处理 500 个源要素 × 50 个叠加图层,完成后
postMessage中间结果,再继续下一批 - 加入
self.onmessage中断响应机制:主线程可发{type: 'cancel'}指令,Worker 清理当前批次后退出,避免用户切换图层时还在后台硬算
结果回传后要快速映射回可视化层
计算完不能直接塞进 Cesium 或 MapLibre;得适配渲染引擎的数据结构:
- 返回结构建议为:
{type: 'overlap-result', features: [...], stats: {total: 1280, intersected: 312}} - Cesium 场景中:将结果转成
EntityCollection或PrimitiveCollection,用createGeometry+combineGeometry在主线程合并后提交 - MapLibre/Leaflet 场景中:生成最小 GeoJSON FeatureCollection,用
addSource+addLayer动态注入,配合setFeatureState控制高亮 - 务必加防抖:若用户连续缩放/平移,只保留最后一次请求的计算结果生效,丢弃中间旧任务

















