第05章 - 数据添加与格式支持
GeoLibre 把”把数据放进来”这件事收敛到一个菜单:Add Data。它按数据来源分成 Files、Web services、Cloud formats、3D layers、Databases 五组,每一组里的条目都对应一个已经实现好的读取器或服务客户端。除此之外还有四条侧路可以进来数据:直接拖拽、左侧 Browser 面板、URL 参数、以及插件面板。
本章按”入口 → 读取器 → 参数 → 限制”的顺序把这条链路讲透,最后给出两张表:一张是各渲染引擎对 Add Data 条目的支持矩阵,一张是”格式 → 入口 → 限制”的完整索引。看懂这两张表,遇到任何一份陌生数据都能在三步之内判断:能不能直接读、该从哪个入口读、读完会丢什么。
说明:本章基于 GeoLibre 3.4。菜单项、参数名、扩展名保留英文原文,叙述用中文。所有条目均来自仓库
docs/data-formats.md、docs/user-guide/adding-data.md、docs/tutorials/supported-formats-zh.md与apps/geolibre-desktop/src/lib/duckdb-vector-loader.ts。
5.1 Add Data 菜单的五个分组
Add Data 是主入口。它不做”文件类型猜测后再让你选”,而是先让你选数据形态:是一个文件、一个服务地址、一个云原生对象、一个三维资产,还是一个数据库连接。选错分组的代价只是多一次点击,不会失败。
| 分组 | 条目数 | 面向的数据 | 典型入口 |
|---|---|---|---|
| Files | 12 | 本地或 URL 上的单文件、成组文件 | Vector Layer、Raster Layer、Delimited Text Layer、CAD、GDB、GPX、LandXML、OSM PBF、MBTiles、Geotagged Photos、Encoded Polyline、ICESat-2 / GEDI |
| Web services | 14 | OGC 服务、ArcGIS 服务、目录、瓦片模板 | XYZ、WMS、WMTS、WFS、WCS、OGC API - Features、OGC Vector Tiles、ArcGIS Layer、CSW、GeoRSS、Administrative Boundaries、STAC、Video、Deck.gl |
| Cloud formats | 5 | 云原生与科学数据对象 | GeoParquet、FlatGeobuf、PMTiles、Zarr、NetCDF / HDF |
| 3D layers | 7 | 三维资产与三维流 | LiDAR、Gaussian Splatting、3D Tiles、Cesium Ion Asset、CZML、KML / KMZ、3D Model (glTF) |
| Databases | 4 | 可查询、可写回的数据源 | DuckDB、PostgreSQL、SQL Server、Apache Iceberg |
5.1.1 Files 组
Files 组里的每一条都对应一个独立的面板,面板内部再做格式细分。
| 条目 | 主要格式 | 关键参数 | 平台限制 |
|---|---|---|---|
| Vector Layer | GeoJSON、GeoParquet、FlatGeobuf、Shapefile(含 ZIP)、GeoPackage、KML/KMZ、GML 及其他 OGR 可读矢量 | 文件或 URL、图层选择、源 CRS(可选) | 全平台 |
| Raster Layer | GeoTIFF、COG | 文件或 URL、波段与色带(读入后在 Style 面板调) | 全平台(本地文件读取需桌面版) |
| Delimited Text Layer | CSV、TSV、自定义分隔符文本、Excel 工作簿 | 分隔符、经度列、纬度列、源 CRS、地理编码地址列 | 全平台 |
| CAD (DXF/DWG) Layer | .dxf、.dwg |
图纸图层(layer)、源 CRS、Render Z values in 3D | 全平台(DXF 走 DuckDB ST_Read) |
| File Geodatabase (GDB) | Esri .gdb 目录 |
要素类(feature class) | 仅桌面版,且需本地 GeoLibre server |
| Geotagged Photos | JPEG、PNG、WebP、HEIC | 一组照片;无坐标的可手动落点 | 全平台 |
| GPX Layer | .gpx |
无(自动拆分航点/轨迹/路线) | 全平台 |
| LandXML Layer | .xml、.landxml |
要导入的 TIN 面、平曲线、纵断面、测量点;源 CRS | 全平台 |
| Encoded Polyline | 文本或文本文件 | 精度 5(Google)或 6(Valhalla/OSRM/Mapbox) | 全平台 |
| MBTiles Layer | .mbtiles(栅格或矢量) |
本地文件 | 仅桌面版 |
| OSM PBF Layer | .osm.pbf |
要加载的要素类别 | 全平台(Worker 内解析) |
| ICESat-2 / GEDI | ICESat-2 ATL06/ATL08/ATL03、GEDI L2A/L2B/L4A 的 .h5 |
波束、字段、质量筛选、当前视图限定、点数上限 | 全平台;ATL03 按视图按需读取 |
提示:Vector Layer 打开的是 Add Vector 面板(由
maplibre-gl-vector支撑),Raster Layer 打开的是 Add Raster 面板(由maplibre-gl-raster支撑)。这两个面板自己也能管理已加载的图层,但它们画成瓦片的图层不会进入 GeoLibre 的图层模型——详见 5.2.8。
5.1.2 Web services 组
| 条目 | 协议/服务 | 参数 | 限制 |
|---|---|---|---|
| XYZ Layer | {z}/{x}/{y} 模板 |
模板 URL、tileSize、minzoom/maxzoom、scheme | 无坐标系约束,模型为 Web Mercator |
| WCS Layer | OGC WCS 1.0.0 | 端点、coverage、范围、请求 CRS、输出像素尺寸 | 仅 1.0.0;必须提供 GeoTIFF 输出;单次子集 |
| WMS Layer | OGC WMS | 端点、图层、样式、格式、透明 | 服务需支持所请求的 CRS(桌面版可换 CRS) |
| CSW Catalog | OGC CSW 2.0.2 | 端点、关键字 | 只打开受支持的关联资源(GeoJSON、WMS、WFS、ArcGIS) |
| WFS Layer | OGC WFS | 端点、typeName、自动刷新 | 优先 GeoJSON,回退 GML |
| WMTS Layer | OGC WMTS | 端点、图层、矩阵集 | 依赖服务自身瓦片矩阵 |
| OGC API - Features | OGC API | landing page / collections / collection / items URL | 自动跟随 next,默认取 1000 条 |
| OGC Vector Tiles | OGC API - Tiles | TileJSON 或 MVT 模板;可选 Mapbox style URL | 需要 source-layer 名 |
| ArcGIS Layer | FeatureServer / VectorTileServer / MapServer / ImageServer | 服务 URL 或门户项目 ID、认证方式、Sublayers、Raster function | 依赖服务与凭证 |
| GeoRSS Layer | RSS 2.0 / Atom / RDF | 订阅 URL 或文件 | GeoRSS Simple 与 GML 几何 |
| Administrative Boundaries | geoBoundaries | 国家、行政级别 | 简化几何为默认,完整几何可达数 MB |
| STAC Layer | STAC API / 静态目录 | 目录、搜索范围 | 只加载可视化资产(GeoTIFF / GeoJSON) |
| Video Layer | 视频叠加 | 视频 URL + 四个角点坐标 | 只支持 URL,不支持本地文件 |
| Deck.gl Layer | deck.gl 可视化规格 | 可视化类型与数据 | 通过共享 deck.gl 叠加层渲染 |
5.1.3 Cloud formats 组
这一组是 GeoLibre 与桌面 GIS 拉开差距的地方:五个条目全部围绕”远程对象 + HTTP Range”设计。
| 条目 | 格式实质 | 读取方式 | 备注 |
|---|---|---|---|
| GeoParquet Layer | 列式矢量 | 与 Vector Layer 共用同一个面板;大文件可流式读取 | 带 Stream GeoParquet (no copy) 开关 |
| FlatGeobuf Layer | 带空间索引的矢量 | 按视图取要素 | 远程 URL 友好 |
| PMTiles Layer | 单文件瓦片档案 | 直接读档案头,自动嗅探矢量/栅格 | 矢量档案可分别添加多个 source layer |
| Zarr Layer | 分块多维数组 | 变量 + 维度选择 | 也支持 Icechunk 仓库 |
| NetCDF / HDF | 科学数据立方 | 选变量与空间/时间/垂直维度 | 云优化版走 Kerchunk 引用 |
5.1.4 3D layers 组
| 条目 | 输入 | 渲染路径 | 引擎限制 |
|---|---|---|---|
| LiDAR Layer | LAS/LAZ/COPC 文件或 URL、EPT 的 ept.json |
maplibre-gl-lidar + deck.gl |
MapLibre/Mapbox;Cesium 与 ArcGIS 走各自适配 |
| Gaussian Splatting | 泼溅场景 URL | maplibre-gl-splat |
仅 MapLibre |
| 3D Tiles Layer | tileset URL(可带鉴权请求头) | deck.gl Tile3DLayer 或 Cesium 原生 |
全引擎(ArcGIS 需 deck.gl 叠加层) |
| Cesium Ion Asset | asset ID + ion token | Cesium 原生 | 仅 Cesium |
| CZML Dynamic 3D Scene | CZML 文档 | Cesium 原生 | 仅 Cesium |
| KML / KMZ | .kml、.kmz |
Cesium 原生或宿主 KML 导入器 | 全引擎 |
| 3D Model (glTF) | .gltf、.glb |
deck.gl ScenegraphLayer |
MapLibre/Mapbox/ArcGIS |
3D Tiles 面板内置一个 Google Photorealistic 3D Tiles 样例,它会从运行时环境读取 VITE_GOOGLE_MAPS_API_KEY 或 GOOGLE_MAPS_API_KEY,密钥通过请求头传递,不写进工程文件。
5.1.5 Databases 组
| 条目 | 连接对象 | 结果形态 | 平台 |
|---|---|---|---|
| DuckDB Layer | DuckDB 或 DuckDB Spatial 数据源 | 查询结果为图层,支持识别、选择、属性表 | 全平台(WASM) |
| PostgreSQL Layer | PostgreSQL / PostGIS | 经本地瓦片服务出 MVT | 仅桌面版 |
| SQL Server Layer | SQL Server / Azure SQL | 空间表,载入后可编辑 | 仅桌面版 |
| Apache Iceberg Layer | Iceberg 表(经 DuckDB) | 空间列作为图层 | 全平台(DuckDB iceberg 扩展) |
5.1.6 菜单之外的四条入口
| 入口 | 位置 | 适用场景 | 与菜单的差异 |
|---|---|---|---|
| 拖拽 | 把文件拖到地图上 | 已知格式的单个文件 | 按扩展名路由,部分格式会拆成多图层(见 5.2.4) |
| Browser 面板 | 窗口左缘的 Browser 标签 | 反复添加同类数据源、先浏览再提交 | 收藏、服务库、最近工程、数据库连接、桌面文件夹 |
| URL 参数 | ?data= 与 ?style= |
分享单图层深链、嵌入 | 数据由 URL 提供,样式可另附文档 |
| 插件面板 | Plugins → Web Services 等 | 目录检索、批量挑选 | 面板内检索,一键加图层 |
拖拽的路由规则(来自 adding-data.md):
- 矢量文件(GeoJSON、ZIP 包 Shapefile、KMZ 等)与 GeoTIFF/COG 直接成为图层。
- GPX 拆成命名的航点、轨迹、路线三个图层。
.osm.pbf解析成点、线、面三个图层。- LAS、LAZ、COPC 进入 LiDAR 控件;LAS 1.4 若无法整体读取,会先转成 COPC。
- JPEG、PNG、WebP、HEIC 照片按 EXIF GPS 落点成点图层。
- 单个
.geolibre.json作为当前工程打开。
URL 参数的形态(来自 layers.md 与 embedding.md):
https://web.geolibre.app/?data=https://assets.geolibre.app/data/places.geojson&style=https://assets.geolibre.app/data/sample.style.json
data 接受 GeoJSON、GeoParquet、矢量 PMTiles 等远程对象,style 接受 GeoLibre URL style、Mapbox/MapLibre style、SLD、QML 四类文档之一(按内容判断,不看扩展名)。样式文档本身必须托管在允许跨域读取的主机上。
5.2 矢量与表格文件的读取链
矢量是 GeoLibre 适配最完整的部分。文件选择器内置统一的格式白名单,共 17 个扩展名,拖拽时按扩展名自动分派,不需要你预先声明格式:
geojson json gpkg geoparquet parquet fgb flatgeobuf
csv tsv kml kmz gml gpx dxf tab shp zip
真正决定实际表现的,不是扩展名,而是每种格式背后是谁在读。
| 格式 | 扩展名 | 读取器 | 值得注意的行为 |
|---|---|---|---|
| GeoJSON | .geojson .json |
原生 JSON.parse |
带老式顶层 crs 成员时改走 DuckDB 重投影到 WGS84 |
| GeoParquet / Parquet | .parquet .geoparquet |
DuckDB read_parquet |
远程文件走 HTTP Range 流式读 |
| FlatGeobuf | .fgb .flatgeobuf |
DuckDB ST_Read |
带空间索引,可按视图取 |
| GeoPackage | .gpkg |
sql.js(SQLite WASM),不是 GDAL | 多图层弹选择器;读取前修复 gpkg_ogr_contents |
| Shapefile(散文件) | .shp |
shpjs | 桌面版自动读同名 .dbf/.shx/.prj/.cpg;3D MultiPatch 改走 DuckDB |
| Shapefile(压缩包) | .zip |
fflate 解压 → shpjs | .prj 决定投影,.cpg 决定 DBF 编码 |
| GML | .gml |
DuckDB ST_Read |
—— |
| MapInfo TAB | .tab |
DuckDB ST_Read |
需要配套文件可访问 |
| KML | .kml |
自研解析器 | 保留内嵌符号化、Folder 结构、GroundOverlay、<Model> |
| KMZ | .kmz |
fflate 解压 + 自研解析器 | 自定义图标与格式化描述保留 |
| GPX | .gpx |
纯 JS | 自动拆成航点/轨迹/路线三个图层 |
| CSV / TSV | .csv .tsv .txt .dat |
自研 + DuckDB 兜底 | 自动识别分隔符与经纬度列;WKT 几何列走 DuckDB |
| Excel | .xlsx .xls |
SheetJS(@e965/xlsx) |
从 Delimited Text 面板进入,先选工作表再选坐标列 |
| CAD | .dxf .dwg |
DuckDB ST_Read |
读出图层清单供挑选;不带坐标系,需手动选 EPSG |
| OSM PBF | .osm.pbf .pbf |
osmix(Web Worker) | 拆成点/线/面;超 50 MB 提示确认,5 分钟超时保护 |
5.2.1 GeoJSON、GeoParquet、FlatGeobuf
三种格式都有独立的 Add Data 条目,也都能从 Vector Layer 进入。
GeoJSON 是最贵的格式:它按文本解析、在内存中展开数倍。仓库里的取舍很明确——能用 GeoParquet、FlatGeobuf、Shapefile 就别用 GeoJSON。GeoJSON 唯一的特权是它直接进内存模型,因此能获得全部样式能力。
GeoParquet 支持多个世代:
- 1.0 与 1.1 文件(含携带
coveringbbox 列的版本); - 2.0 文件,使用 Parquet 原生
GEOMETRY/GEOGRAPHY逻辑类型; - 几何只是 WKB 二进制列、列名约定为
geom之类的普通 Parquet。
判定依据是文件里的 geo 元数据块:它决定哪一列是几何、CRS 是什么。一个声明 "crs": null 的文件是在声明它的坐标不属于任何已知参考系统,GeoLibre 会按原样绘制、不做变换——这是正确行为,不要误判为”投影丢失”。
当文件里有多列几何时,只加载元数据声明为 primary 的那一列。
FlatGeobuf 走 DuckDB ST_Read,格式本身带空间索引,因此按视图取要素是它的常规用法。
5.2.2 Shapefile:散文件与 ZIP
Shapefile 从来不是一个文件。GeoLibre 对两种形态的处理完全不同:
| 形态 | 需要的伙伴文件 | 行为 |
|---|---|---|
散文件 .shp |
.shx、.dbf、.prj、.cpg |
桌面版自动发现同名文件;浏览器端无法读取同级目录 |
压缩包 .zip |
上述文件打包在一起 | fflate 解压,自动跳过 macOS 的 __MACOSX |
两个伙伴文件值得单独说明:
.prj决定投影。没有.prj的 Shapefile 按无 CRS 处理,坐标原样绘制。.cpg决定 DBF 的字符编码。中文属性乱码通常就是这一步没生效——打包时保留.cpg基本可以解决;若仍乱码,说明原始数据本身缺少.cpg,需要在源头补。
3D MultiPatch(三维建筑)不能走 shpjs,会改走 DuckDB 的 ST_Read,再由 JS 侧解码 TIN 面(见 5.8.4)。
5.2.3 GeoPackage 与 MapInfo TAB
GeoPackage 是本章里最反直觉的一条:它不由 GDAL 读,而由 sql.js(SQLite WASM)读。原因写在 gpkg-reader.ts 与 issue #393 里——DuckDB-WASM 是单线程构建,而 GDAL 在填充 Arrow 批次时会用后台线程,超过很小规模就会崩。
所以链路上多了三步:
- 先判断文件头是不是真的 SQLite(扩展名写错的文件会落回通用
ST_Read路径); - 修复缺失的
gpkg_ogr_contents(否则要素计数会让单线程 WASM 构建崩溃); - 读出 WKB 后,若图层不是 EPSG:4326,再用 DuckDB 的
ST_Transform重投影到 WGS84。
MapInfo TAB 走 ST_Read,但需要那组配套文件(.tab、.dat、.map、.id)都可访问,浏览器端基本只能靠打包上传。
5.2.4 KML / KMZ / GPX / GeoRSS
KML 由自研解析器读取,这是刻意的设计:只有自己解析,才能保留文件自带的符号化,让带样式的 KML 在 GeoLibre 里渲染得和 Google Earth 一致。解析器处理不了的文件回退到 DuckDB Spatial,此时几何还在,样式丢失。
KML 里几类”非几何内容”也有专门处理:
| KML 元素 | 处理方式 |
|---|---|
<Folder> 层级 |
保留结构 |
<Style> / <StyleMap> |
转成 simplestyle 属性,逐要素生效 |
GroundOverlay |
作为图像叠加层;带 <TimeSpan> 的可接时间轴 |
<Model>(COLLADA .dae) |
three.js 载入后转 GLB 显示 |
NetworkLink 驱动的 Super-Overlay |
直接把档案里的瓦片喂给地图,不整金字塔加载 |
| 远程图标 URL | 打开时从公共主机下载并内联保存;指向回环或私网地址的图标被跳过,且不跟随重定向 |
KMZ 是 KML 的 ZIP 封装,用 fflate 解压后走同一条解析链。
GPX 由纯 JS 读取,并且自动拆成三个图层:航点(waypoints)、轨迹(tracks)、路线(routes)。拖拽 GPX 时同样拆分,图层名带来源文件前缀。
GeoRSS 支持 RSS 2.0、Atom、RDF 三种载体,几何用 GeoRSS Simple 或 GML 表达;feed 的标题与描述成为属性。
5.2.5 CSV、TSV 与 Excel:Delimited Text 面板
分隔文本面板承担三种任务:坐标列建点、WKT 建几何、非空间属性表。
坐标列建点的完整流程:
- 打开 Add Data → Delimited Text Layer,选文件或填 URL。
- 分隔符默认自动识别;识别不准时手动指定。
- 面板读出表头后,选择 经度列 与 纬度列。
- 指定 源 CRS(默认按 WGS84 处理);若你的坐标是投影坐标(例如某地的地方格网),必须在这里改,否则点会落在错误位置。
- 点击加载。结果是一个点图层,属性列来自 CSV 的其余列。
三种特殊情况:
- WKT 几何列:表中存在 WKT 字段时可以选择按 WKT 建几何,此时走 DuckDB 而不是 JS 解析器。
- 地址地理编码:没有坐标但有地址列时,可以对一个或多个地址列做地理编码(提供商在 Settings 里配置)。
- 完全无坐标:可以只作为非空间属性表加入工程,供连接(join)与虚拟字段使用。
Excel 从同一个面板进入:先选工作表,再选坐标列。读取器是 SheetJS(@e965/xlsx),.xlsx 与 .xls 都支持。
注意:CSV 的字段类型是推断出来的,不是声明出来的。一个看起来像数字的编号列(例如
0755、100010)可能被推断成数字而丢掉前导零。需要保留编码语义时,改用文本列或在载入后用虚拟字段重建。
5.2.6 CAD、GML、LandXML、GDB、OSM PBF、编码折线
| 格式 | 关键行为 | 必须提供的参数 |
|---|---|---|
| CAD (DXF/DWG) | 实体转矢量要素;Z 值保留并在三维中渲染(除非取消 Render Z values in 3D);先读出图层清单让你挑 | 源 CRS(CAD 不自带)+ 图纸图层 |
| GML | 走 ST_Read;GML 2 / 3.1 / 3.2 均可 |
源 CRS(可从文件读则免填) |
| LandXML | 导入 TIN 面、平曲线、纵断面元数据、测量点 | 源 CRS(投影坐标必须提供) |
| File Geodatabase | 由本地 GeoLibre server 读取,选一个要素类 | 桌面版;Mac App Store 版隐藏该入口 |
| OSM PBF | Worker 内解析,拆成点/线/面;> 50 MB 需确认;5 分钟超时 | 要加载的要素类别 |
| Encoded Polyline | 精度 5(Google)或 6(Valhalla/OSRM/Mapbox);粘贴文本或上传文本文件 | 精度选择 |
CAD 的编码有一个细节:WASM 版 GDAL 没有 iconv,DXF 的文本会乱码,因此 GeoLibre 在 ST_Read 之前先读 $DWGCODEPAGE / $ACADVER,读完再按该代码页重编码文本字段(cad-encoding.ts)。这就是为什么中文 DXF 的标注文字能正常显示。
5.2.7 大文件的 100 MB 与 10 万要素阈值
GeoLibre 对”大”有两套互不相同的判据,都很重要:
| 判据 | 阈值 | 触发什么 | 说明 |
|---|---|---|---|
| 文件大小 | 100 MB | 改用 DuckDB 流式读取(主线程之外) | 小于 100 MB 走内存 JS 读取器,日常数据最快;ZIP 包 Shapefile 按解压后的 .shp 计 |
| 要素数 | 100,000 | 弹确认,再决定是否全部转成 GeoJSON | 内存而非文件大小才是真正的瓶颈:一份小的 GeoParquet 可能有上百万行 |
这两个阈值都不需要你设置,全部自动判断。但选择权在你手里:
- 上百万要素的远程数据,优先 Vector to PMTiles(Processing → GeoLibre Toolbox → Conversion → Vector to PMTiles),瓦片化后地图一次只读一个瓦片。
- 需要紧凑、读得快的中间格式,转 GeoParquet;它是列式的,但不瓦片化。
- 尽量不用 GeoJSON 作为中间态——它在内存里要膨胀数倍。
5.2.8 “移交给 GeoLibre” 的矢量图层
Add Vector 面板不是所有图层都交给 GeoLibre 管理。规则是:
在 GeoJSON 模式下加载、且要素数不超过 100,000 的图层,加载完成后移交给 GeoLibre,此后获得与拖拽文件完全相同的 Style 面板能力:连接、虚拟字段、属性表单、弹窗设计、编辑追踪、图表、几何生成器。
面板自己保留的图层是:画成瓦片的、流式 GeoParquet、更大的图层、带地标图标的 KML/KMZ。这些图层没有要素存在 GeoLibre 里,因此:
| 能力 | 移交的图层 | 面板保留的图层 |
|---|---|---|
| 字段连接 / 虚拟字段 | 有 | 无 |
| 属性表 | 有 | 面板自带的原始表 |
| 弹窗设计器 | 有 | 无(面板有自己的 Popup 复选框) |
| 分类/分级/规则/表达式符号化 | 有 | 仅面板能画的设置 |
| 项目重开 | 按 URL 或文件路径重开 | 同左 |
理解这条边界很关键:当你发现”这个图层没有 Popup 设计器”时,通常不是 bug,而是它还在面板手里。
5.3 栅格、瓦片档案与多维数组
| 格式 | 扩展名 / 来源 | 入口 | 备注 |
|---|---|---|---|
| GeoTIFF / COG | .tif .tiff、远程 URL |
Raster Layer | 像素检视、符号化、导出、栅格分析;COG 支持远程部分读取 |
| PMTiles | .pmtiles、远程 URL |
PMTiles Layer | 矢量与栅格档案;矢量档案可按 source layer 分别添加 |
| MBTiles | .mbtiles |
MBTiles Layer | 本地栅格或矢量档案;需桌面文件系统 |
| Zarr | 远程 store 或本地文件夹 | Zarr Layer | 多维数组,变量与维度可选;也支持 Icechunk |
| NetCDF-4 / HDF5 | 本地文件 | NetCDF / HDF | 选变量与空间/时间/垂直维度 |
| 云优化 NetCDF / HDF | Kerchunk 引用 | NetCDF / HDF | 按引用读远程分块 |
| MosaicJSON / STAC item | .json |
读取时按需拼接 | 与 STAC 面板配合 |
5.3.1 GeoTIFF 与 COG
默认读取器是 cog-tiler-wasm,可以切到 GPU 引擎。桌面版读本地文件时走 Tauri asset 协议,因此本地大 GeoTIFF 也是 Range 读,不需要整份进内存。
COG 的”部分读取”取决于文件内部是否按瓦片组织、是否带 overview。一张重写过(gdal_translate -of COG)的 GeoTIFF 才真正是 COG;把普通 GeoTIFF 改后缀不会获得这个能力。
载入后进入 Style 面板 → Raster symbology(详见第07章 样式符号化与图例)。
5.3.2 MBTiles 与 PMTiles
两者的定位完全不同:
| 维度 | MBTiles | PMTiles |
|---|---|---|
| 存储 | SQLite 数据库 | 单文件 + 目录(directory) |
| 读取 | 自定义协议 + Rust 后端 | 纯 HTTP Range |
| 平台 | 桌面版专属 | 全平台 |
| 远程 | 不支持(本地文件) | 支持 |
| 内容 | 栅格或矢量瓦片 | 栅格或矢量瓦片 |
| 底图 | 可作离线底图(MapLibre 专属) | 可作底图源 |
PMTiles 会自动嗅探档案头判断矢量还是栅格,因此不需要你选类型。矢量档案可能含多个 source layer,每个可以独立添加、独立设样式。
5.3.3 Zarr 与 NetCDF / HDF
Zarr 是分块的多维数组,GeoLibre 把它当成”可切片的图层”:选变量、选维度的具体坐标值,选中的切片变成地图上的栅格或图像。
本地 Zarr 文件夹在浏览器里依赖 File System Access API,Firefox 与 Safari 用不了;远程 store 没有这个限制。
NetCDF / HDF 的两条路:
- 远程:走 Kerchunk 引用 JSON + HTTP Range,等于”云优化的 NetCDF”。
- 本地:
.nc、.nc4、.cdf、.h5、.hdf5。NetCDF-3 用 netcdfjs,NetCDF-4/HDF5 用 h5wasm。
HDF4 的 .hdf 明确不支持——这不是配置问题,是读取器不在依赖列表里。
5.3.4 栅格格式的不对等
这里有一个非常容易踩的坑:转换工具能读的格式,远多于图层入口能读的格式。
| 场景 | 可接受的栅格格式 |
|---|---|
| 直接作为图层拖入 / Raster Layer | GeoTIFF、COG(.tif .tiff) |
| 转换工具输入(桌面版) | .tif .tiff .img .vrt .asc .nc .jp2 .hgt |
| 转换工具输入(浏览器) | 仅 .tif .tiff |
| Whitebox 栅格 I/O | .tif .tiff .img .bil .flt .sdat .rdc .asc |
也就是说,拿到一份 .jp2 时正确的动作是:先用 Processing → GeoLibre Toolbox → Conversion → Raster to COG 转成 COG,再作为图层加载。
5.4 OGC 服务与 ArcGIS 服务
5.4.1 XYZ、WMS、WMTS
| 服务 | 面板做什么 | 常用参数 | 坑 |
|---|---|---|---|
| XYZ | 直接构造瓦片模板 | {z}/{x}/{y}、tileSize、minzoom/maxzoom、scheme |
TMS(y 轴翻转)与 {-y}、{quadkey} 模板需要显式设置 |
| WMS | 拉 GetCapabilities,生成图层下拉框 | 图层、样式、格式、透明、版本 | 请求 CRS 由地图决定;桌面版可换 CRS 后由地图重投影到 Web Mercator |
| WMTS | 拉能力文档,选图层与矩阵集 | 图层、矩阵集、格式 | RESTful 模板与 KVP 两种风格由面板适配 |
WMS 的 GetFeatureInfo 支持”点击识别”:在地图上点一个位置,服务返回该点的属性。这依赖服务端开启该操作,不是所有 WMS 都提供。
5.4.2 WFS 与 GML 回退
WFS 的加载策略是”先要 GeoJSON,拿不到再要 GML“。这条策略解决了一大批只输出 GML 的服务(MapServer、多数 INSPIRE 服务)。
GML 的 CRS 处理有明确边界:
| 源 CRS | 处理 |
|---|---|
| WGS84、ETRS89、NAD83、Web Mercator | 直接读取 |
| 其他 EPSG(国家格网、UTM 带) | 重投影 |
| GeoLibre 不认识的系统 | 报错,不会画到错误位置 |
WFS 还支持自动刷新(定时重新拉取),适合盯一个持续更新的要素服务。
在桌面版里,WFS 请求走原生 HTTP 客户端,因此不发 CORS 头的服务也能加载;浏览器版必须服务端允许跨域。
5.4.3 WCS 1.0.0:取数值栅格子集
WCS 与 WMS 的本质区别:WMS 返回渲染好的图片,WCS 返回带像素值的 GeoTIFF。要拿像素值做分析、调色带、导出,就必须用 WCS。
完整流程:
- Add Data → WCS Layer,填入服务的 WCS 端点,点 Retrieve coverages。
- 选一个 coverage,然后选范围:Use view(当前视图)、Use coverage extent(coverage 自身范围),或手动输入 west / south / east / north(十进制度)。
- 选 Request CRS:
EPSG:4326、EPSG:3857,或 Automatic。 - 设置输出宽高(像素),点 Add layer。
- 加载后用像素检视器或栅格工具处理;要留副本就 Export 成 GeoTIFF。
参数与限制必须记住:
| 项 | 值 |
|---|---|
| 协议版本 | 仅 WCS 1.0.0(KVP 的 GetCapabilities / DescribeCoverage / GetCoverage) |
| 输出格式 | 服务必须声明 GeoTIFF |
| 请求 CRS | EPSG:4326 或 EPSG:3857;范围始终按经纬度输入后再投影 |
| Automatic 的选择顺序 | 4326 → 3857 → 仍试 4326(很多服务会响应未声明的 CRS) |
| 单边像素 | 1–4096 |
| 单次下载 | 128 MB;能力列表 32 MB |
| 跨 180° 经线 | 必须拆成两次请求 |
| 平移 | 不会继续取数,每次加载是固定子集 |
另有两条实用行为:MapServer 常见的条纹状 GeoTIFF 响应会在浏览器里先转成 COG 再加载;直接粘一个 ArcGIS ImageServer 的 REST URL 也能用,GeoLibre 会把它换算成对应的 WCS 端点。
警告:WCS 下载的栅格是文件支撑的图层,遵循与其他导入 GeoTIFF 相同的持久化规则。只保存工程不会保留下载到的像素——结束会话前请导出 GeoTIFF。
5.4.4 OGC API - Features 与 OGC API - Tiles
OGC API - Features 接受四种 URL 形态:落地页、/collections、单个集合、以及完整的 /items URL。它会自动跟随响应里的 next 链接翻页,默认取 1000 条。
OGC Vector Tiles 接受 TileJSON 或 {z}/{x}/{y} 的 MVT 模板;如果瓦片里用了命名 source layer,需要额外填 Mapbox style URL 让它解析出 source-layer 名。
5.4.5 ArcGIS 的四种图层类型
ArcGIS 面板的第一件事是选对 Layer type,这决定后续完全不同的加载路径。
| Layer type | 服务的 REST 类型 | 加载方式 | 获得的能力 |
|---|---|---|---|
| Feature layer | FeatureServer | 分页下载成 GeoJSON 图层 | 标注、属性表、识别、符号化、导出 |
| Vector tile layer | VectorTileServer | 按服务自带样式渲染 | 矢量瓦片与样式 |
| Map service | MapServer | 栅格图层;缓存服务读瓦片,动态服务按瓦片走 /export |
透明度、样式面板的亮度/对比度/饱和度、排序、存工程 |
| Image service | ImageServer | 走 /exportImage 或服务的瓦片缓存 |
同上 |
两个可选字段决定服务画什么:
- Sublayers(Map service):要绘制的子图层 id,例如
0,2,5。留空用服务默认集合。粘贴以子图层 id 结尾的 URL(.../MapServer/3)会自动帮你选中该子图层。 - Raster function(Image service):可从服务公布的功能里用 Browse functions 选;Rendering rule 字段保留给高级的 Esri 栅格函数 JSON,例如
{"rasterFunction":"Hillshade"}。
注意:一旦设置了 Sublayers 或 Raster function,服务就会转为动态绘制——缓存瓦片是在这些选择存在之前渲染的,无法反映它们。
安全服务需要 Authentication:选 Sign in with ArcGIS 或粘贴 access token。也可以直接填门户项目 ID 而不是服务 URL。
5.4.6 目录类服务:CSW、STAC、geoBoundaries
| 服务 | 检索什么 | 加入什么 |
|---|---|---|
| CSW Catalog | OGC CSW 2.0.2 的元数据记录 | 记录关联的 GeoJSON、WMS、WFS、ArcGIS 资源 |
| STAC Layer | STAC 目录(静态或 API,经 STAC Index 发现) | 匹配的栅格资产(GeoTIFF / GeoJSON) |
| Administrative Boundaries | geoBoundaries | 国家 + 行政级别的多边形;默认简化几何 |
STAC 面板除了搜索还能画 bbox 框选、显示足迹(footprints)、选中后加图层。它不加载”任何资产”,只加载可视化资产——一个只提供原始 COG 集合而没有可视化元数据的目录,在面板里可能看起来”没有数据”。
5.5 3D、点云与三维资产
5.5.1 LiDAR 点云
| 能力 | 说明 |
|---|---|
| 输入 | LAS / LAZ / COPC 的本地文件或 URL、EPT 的 ept.json URL |
| 渲染 | maplibre-gl-lidar + deck.gl |
| 拖拽 | LAS/LAZ/COPC 直接拖到地图;LAS 1.4 无法整体读取时先转 COPC |
| 导出 | 图层菜单可导出 LAS、LAZ、COPC |
| 工具产物 | Whitebox LiDAR 工具的输出作为新的点云图层加载 |
| 特例 | .e57、.ply 只出现在 Whitebox LiDAR 工具的输入里,不是图层入口 |
本地 COPC 按八叉树节点流式加载,不会整份复制进内存。
点云的分析流程见第17章 点云与 LiDAR 分析。
5.5.2 3D Tiles 与 I3S
3D Tiles 是 OGC 的三维流式标准,GeoLibre 用 deck.gl 的 Tile3DLayer 承载(Cesium 引擎下用原生实现)。
| 项 | 值 |
|---|---|
| 输入 | tileset.json 的 URL |
| 鉴权 | 支持自定义请求头,因此带 token 的私有 tileset 也能加 |
| 存档 | 随工程恢复 |
| 内置样例 | Google Photorealistic 3D Tiles(需 VITE_GOOGLE_MAPS_API_KEY 或 GOOGLE_MAPS_API_KEY) |
| I3S | 填 .../SceneServer 形式的 URL,经 loaders.gl 的 I3SLoader 读取,支持 Integrated Mesh 与 3D Object 场景图层 |
5.5.3 Cesium ion 与 CZML
这两条是 Cesium 引擎专属,在二维引擎上入口被禁用:
- Cesium Ion Asset:按 asset ID 加 3D Tiles tileset 或影像,使用你的 Cesium ion token。
- CZML Dynamic 3D Scene:载入 CZML 文档,用于轨道、轨迹、车辆路径等带时间变化的三维场景。
5.5.4 glTF、高斯泼溅、视频与照片
3D Model (glTF) 把 .gltf/.glb 模型放到指定坐标,可设缩放、旋转、高度。渲染走 deck.gl 的 ScenegraphLayer。
Gaussian Splatting 是高斯泼溅场景,存储层类型是 gaussian-splat,渲染器是 maplibre-gl-splat,仅 MapLibre 引擎。
Video Layer 把视频按四个角点铺在地图上(与 MapLibre 的 video source 同机制),只支持 URL。
Geotagged Photos 读 EXIF 的 GPS 标签,每张照片生成一个带缩略图的点;没有坐标的照片可以手动落点。
Deck.gl Layer 直接渲染一份 deck.gl 图层规格,覆盖 MapLibre 自身图层类型表达不了的可视化。支持的 14 种可视化类型:
散点 Scatterplot 热力 Heatmap 六边形 Hexagon
格网 Grid 屏幕格网 Screen Grid 等值线 Contour
弧线 Arc 线 Line 大圆 Great Circle
GeoJSON 图标 Icon 文本 Text
轨迹 Trips 场景图 Scenegraph
5.5.5 各渲染引擎对 Add Data 条目的支持矩阵
菜单里能看到不等于当前引擎能加。这层门控写在 apps/geolibre-desktop/src/lib/add-data-renderer.ts,逻辑是三个”不支持集合”:
const MAPBOX_UNSUPPORTED_SOURCES = new Set(["mbtiles", "splatting", "cesium-ion", "czml"]);
const ARCGIS_UNSUPPORTED_SOURCES = new Set([
...[...MAPBOX_UNSUPPORTED_SOURCES].filter((id) => id !== "mbtiles"),
"stac",
"video",
]);
const ARCGIS_DECK_SOURCES = new Set(["deckgl-viz", "gltf-model", "lidar", "duckdb", "3d-tiles"]);
const CESIUM_UNSUPPORTED_SOURCES = new Set(["lidar", "splatting"]);
由此得到的矩阵:
| 数据源 | MapLibre | Mapbox | Cesium | ArcGIS |
|---|---|---|---|---|
| MBTiles | 有 | 无 | 有 | 有 |
| 高斯泼溅 | 有 | 无 | 无 | 无 |
| Cesium ion / CZML | 无 | 无 | 有 | 无 |
| STAC | 有 | 有 | 有 | 无 |
| Video | 有 | 有 | 有 | 无 |
| LiDAR | 有 | 有(deck.gl) | 无(原生走 3D Tiles) | 有(deck.gl) |
| Deck.gl / glTF / DuckDB / 3D Tiles | 有 | 有 | 视能力 | 需 deck.gl 叠加层 |
ArcGIS 有一个额外条件:那些走 deck.gl 的源要求引擎提供 deckOverlay 能力,且只在主平面图或局部三维场景上生效,全局球面与分屏面板不承载该叠加层。
5.6 云原生格式与在线目录
5.6.1 四种云原生格式
| 格式 | 面向 | 关键特性 | 增量读取的基础 |
|---|---|---|---|
| GeoParquet | 矢量 | 列式、压缩、带 geo 元数据 |
row group 级 HTTP Range |
| FlatGeobuf | 矢量 | 内建空间索引(packed Hilbert R-tree) | 按索引定位,取视图内要素 |
| COG | 栅格 | 内部瓦片 + overview | 只取需要的瓦片与层级 |
| PMTiles | 瓦片 | 单文件、内建目录 | 目录给出字节偏移,按需取瓦片 |
这四种格式的共同点是:读取成本与”你正在看的那一块”成正比,而不是与文件总大小成正比。
5.6.2 流式读取
Stream GeoParquet (no copy) 是 GeoParquet 面板上的一个开关。打开后,GeoLibre 用 HTTP Range 就地查询,不把文件复制进内存。
它的前提是行按空间有序排列(例如 Hilbert 序,GeoLibre 自己的 Conversion 工具写出的文件就是这种序),这样一次查询只需要拉取相关的 row group。乱序文件打开这个开关不会出错,但也不会快。
FlatGeobuf、COG、PMTiles 的增量读取不需要开关,格式本身决定了行为。
5.6.3 在线目录与数据提供方
| 目录 / 提供方 | 内容 | 入口 |
|---|---|---|
| STAC | 通用影像目录(经 STAC Index 发现) | Add Data → STAC Layer / Plugins |
| Source Cooperative | 桶浏览器,认 .pmtiles .parquet .geoparquet .tif .geojson .geojsonl .ndjson .fgb .gpkg .csv |
Plugins 面板 |
| Natural Earth | 锁定到 opengeos/natural-earth 的 Source Cooperative 面板 |
Plugins 面板 |
| Hugging Face Hub | 数据集仓库浏览与上传 | Plugins 面板 |
| Overture Maps | 主题化矢量瓦片(默认只显示建筑) | Plugins 面板 |
| Microsoft Planetary Computer | STAC + TiTiler | Plugins 面板 |
| Google Earth Engine | OAuth 登录,桌面版有原生 OAuth 流程 | Plugins 面板 |
| NASA Earthdata GIS | EOSDIS 的 ImageServer / MapServer / FeatureServer / web map | Plugins 面板 |
| OpenAerialMap / Esri Wayback / Mapillary / Street View | 影像与街景 | Plugins 面板 |
| FEMA NFHL / EPA EnviroAtlas / USGS National Map | 联邦数据服务 | Plugins → Web Services |
| RainViewer / NASA GIBS / EOX | 气象与年度无云底图 | Plugins 面板 |
其中 ArcGIS Hub、Socrata、CKAN 三个面板被明确归在 Plugins → Web Services 下,都能按关键字检索公开目录并一键加图层;每个面板都会显示”当前看到的结果数 / 总数”并提供 Load more 翻页。ArcGIS Hub 还支持限定当前地图范围、缩放到结果、下载数据——但多图层数据集只下载第一个图层,面板会明说这点。
5.6.4 一个完整的云原生加载流程
以”远程 GeoParquet + 远程 COG”为例,串起本章的主要概念:
- 打开 Add Data → GeoParquet Layer,填入:
https://data.source.coop/giswqs/opengeos/countries.parquet - 勾选 Stream GeoParquet (no copy),点 Load。
- 图层出现在 Layers 面板;若总要素数超过 10 万,会先弹确认。
- 打开 Add Data → Raster Layer,填入一张 COG 的
.tifURL 并加载。 - 在 Style 面板 调整亮度、对比度、饱和度、色相。
- 若要把本地数据也变成云原生格式:Processing → GeoLibre Toolbox → Conversion → Vector to GeoParquet(浏览器端跑 DuckDB-WASM)或 Raster to COG(浏览器端跑 WebAssembly,桌面端跑 sidecar 并支持更多输入格式)。
- 转换完成后把产物重新加回地图验证。
提示:在浏览器构建里,Vector to GeoParquet 与 CSV to GeoParquet 跑在 DuckDB-WASM 上,Vector to FlatGeobuf、Vector to PMTiles、Raster to COG 跑在
geolibre-wasm上,都不需要 sidecar。桌面版改用 Python sidecar,能读更多输入格式,也能保留浏览器写入器无法保留的数据类型。
5.7 数据库与查询型数据源
5.7.1 DuckDB Layer
DuckDB 是 GeoLibre 的计算底座:浏览器里是 DuckDB-WASM Spatial,SQL 工作区另有一个独立实例。
Add Data → DuckDB Layer 的用途是”查询即图层”:写一条查询、拿到结果、作为图层加入。得到的图层支持识别、选择、属性表——与普通矢量图层一致。
三个后续动作值得记住:
| 动作 | 位置 | 结果 |
|---|---|---|
| Materialize to editable layer | 图层的 Layer actions | 把查询结果复制成可编辑的 GeoJSON 图层 |
| Edit query in SQL Workspace | SQL 查询图层的 Layer actions | 在 SQL 工作区重开该查询 |
| 刷新 | 图层 Layer actions | 重新执行查询 |
5.7.2 PostgreSQL / PostGIS
桌面版专属,链路是”连接 → 选表 → 出 MVT”,由内置的 Martin 瓦片服务承担。浏览器版没有本地进程,因此没有这条路径。
连接管理在 Browser 面板 → Databases:每个引擎一个分组,组头有 + 新建连接。展开连接可浏览 schema 与空间表,Add Data 表单会保留各引擎自己的表选项。
注意:连接删除涉及系统钥匙串。若钥匙串无法立即删除凭据,GeoLibre 会显示一条持久警告(带掩码的连接标签)并在下次启动时重试;不同连接的失败会分别报告,不会互相掩盖。
5.7.3 SQL Server / Azure SQL
同样桌面版专属,空间表载入后是可编辑图层,改动可以写回(Layer actions → Save edits to SQL Server table)。
SQL Server 有一条额外的保护:一次写回需要先成功重读表才能再次提交(记录在图层记录的 mssqlWritebackPending 上),避免并发覆盖。
5.7.4 Iceberg、PGlite 与 Sedona
| 源 | 入口 | 说明 |
|---|---|---|
| Apache Iceberg | Add Data → Apache Iceberg Layer | 经 DuckDB 的 iceberg 扩展读表,空间列作为图层 |
| PostGIS via PGlite | SQL 工作区 | 浏览器内的空间 SQL 引擎 |
| Apache Sedona | SQL 工作区 | 额外的空间查询引擎,sidecar 或浏览器 WASM 版 |
在 SQL 侧的深入用法见第11章 SQL 工作区与 DuckDB 空间分析。
5.8 浏览器内转换链路
这一节是”怎么开发”的部分:数据从字节到图层,中间经过了哪些组件。
5.8.1 从文件到 FeatureCollection
统一入口是 apps/geolibre-desktop/src/lib/duckdb-vector-loader.ts 导出的 loadDuckDbVectorFile:
export async function loadDuckDbVectorFile(
file: DuckDbVectorFile,
options: DuckDbVectorLoadOptions = {},
): Promise<FeatureCollection>
DuckDbVectorFile 的形状是:
export interface DuckDbVectorFile {
name: string;
extension: string;
data: Uint8Array<ArrayBuffer>;
siblingFiles?: DuckDbVectorFile[];
}
函数内部的顺序是固定的一条流水线:
- 若是
.gpkg且文件头真是 SQLite,转loadGeoPackageVector(不走 DuckDB)。 - 捕获
.prj的 CRS 文本(必须在注册文件缓冲之前,因为registerFileBuffer会把 ArrayBuffer 转移给 Worker)。 - DXF 先读
$DWGCODEPAGE(同理,注册后字节就没了)。 registerVectorFileBuffers注册文件与伙伴文件;GeoPackage 先修gpkg_ogr_contents。ensureSpatialExtension装spatial扩展(Parquet 输入要先做一次 warm-up)。- 生成源 SQL:Parquet 用
read_parquet,其余用ST_Read。 DESCRIBE出列结构 → 识别几何列。- 解析源 CRS。
- 大要素数确认 → 执行带
ST_AsGeoJSON的查询 → 组装 FeatureCollection。 - 错误分支:面几何(TIN / PolyhedralSurface)走 keep_wkb 回退。
源 SQL 的构造只有两个分支:
function sourceSql(fileName: string, extension: string, layer?: string): string {
const quotedName = quoteSqlString(fileName);
if (isParquetExtension(extension)) {
return `SELECT * FROM read_parquet(${quotedName})`;
}
return `SELECT * FROM ST_Read(${quotedName}${layerArgSql(layer)})`;
}
layer= 参数只对多图层源有意义(典型是 CAD 图纸),不指定时读第一个图层。
5.8.2 DuckDB-WASM 的初始化与扩展装载
DuckDB 实例是惰性构建 + memo 化的:
export async function ensureSpatialExtension(
db: duckdb.AsyncDuckDB,
connection: duckdb.AsyncDuckDBConnection,
beforeLoad?: () => Promise<void>,
): Promise<void> {
// ...
await connection.query("INSTALL spatial");
await connection.query("LOAD spatial");
}
三个工程化细节:
- JS 包延迟加载:
@duckdb/duckdb-wasm的 JS 约 0.4 MB,直到第一个数据库创建时才动态 import,不占启动时间。 - 单例失败不缓存:
getDatabase()在构建失败时会清掉 memo(用身份守卫避免并发重建被覆盖),否则一次 CDN 抖动会让后续所有调用永久失败。 - 离线/内网可换扩展源:设置
VITE_DUCKDB_SPATIAL_EXTENSION_PATH时跳过INSTALL,直接从本地路径LOAD。
SQL 工作区用的是另一个实例(getSqlDatabase())。这不是洁癖:duckdb-wasm 1.33.1-dev45 在一个先 LOAD spatial、后读远程 Parquet 的连接上会永久破坏 read_parquet(报 stoi: no conversion),且无法就地恢复。把 SQL 工作区隔离出去后,重建实例时可以安全终止旧 Worker,不影响正在进行的矢量加载、导出与重投影。
5.8.3 五条专用通道
| 通道 | 负责 | 为什么单独实现 |
|---|---|---|
| shpjs | Shapefile(散文件与 ZIP 内的 .shp) |
只需 .shp/.dbf/.prj/.cpg,比启 GDAL 轻 |
| fflate | ZIP / KMZ 解压 | 纯 JS,流式解压,无原生依赖 |
| sql.js | GeoPackage | 避开 DuckDB-WASM 单线程下的 GDAL 线程崩溃 |
| osmix | OSM PBF | 跑在 Web Worker,避免 PBF 解析卡住主线程 |
| exifr | 照片 EXIF GPS | 只读元数据,不解码整张图 |
还有一个”借道”通道:three.js。它只为一件事而存在——把 KML <Model> 里内嵌的 COLLADA .dae 转成 GLB。
5.8.4 四个已知兼容性补丁
这些补丁是源码里写明了 issue 编号的真实工程决策,读它们比读功能列表更能理解这套链路。
① Parquet + spatial 的装载顺序(duckdb-wasm 1.33.1-dev45)
在同一个连接上先 LOAD spatial 再第一次读 Parquet,会抛 Invalid Error: stoi: no conversion。修法是给 ensureSpatialExtension 传一个 beforeLoad:
function parquetWarmUp(
connection: duckdb.AsyncDuckDBConnection,
extension: string,
fileName: string,
): (() => Promise<void>) | undefined {
if (!isParquetExtension(extension)) return undefined;
return async () => {
await connection.query(`SELECT 1 FROM read_parquet(${quoteSqlString(fileName)}) LIMIT 0`);
};
}
先读一次 LIMIT 0,把连接的远程读路径预热,后续的 DESCRIBE / SELECT 就正常了。
② GeoPackage 的 gpkg_ogr_contents(issue #258)
单线程 WASM 构建上,缺少 gpkg_ogr_contents 的 GeoPackage 会让 ST_Read 崩溃。ensureGpkgFeatureCount 会在注册缓冲前把这张表补上。
③ 面几何的 WKB 回退(issue #1121)
DuckDB Spatial 的 WKB 读取器拒绝 TIN / PolyhedralSurface,而它自带的 GDAL 会把 ESRI MultiPatch Shapefile(三维建筑)产出为这类几何。修法是重读原始 WKB 在 JS 侧解码,把 TIN 三角形变成 MultiPolygon。
触发条件有讲究:报错信息里点名了面类型的,任何格式都信任;只给泛化 “Unsupported geometry type in WKB” 的,只对 Shapefile 信任——因为 Shapefile 可能出现的面几何只有 MultiPatch。
④ .prj 兜底(issue #1148)
某些 GDAL/PROJ 构建对”到 WGS84 是格网变换而非 7 参数”的基准(典型是 OSGB36 / EPSG:27700)会在 ST_Read_Meta 阶段抛 “cannot be formatted as WKT1 TOWGS84 parameters”。此时若 Shapefile 带 .prj,就直接用 .prj 的 WKT 重投影,而不是放弃。
5.8.5 平台能力矩阵
| 限制类别 | 影响的功能 |
|---|---|
| 桌面端(Tauri)专属 | 原生文件/文件夹对话框、本地 MBTiles、本地栅格读取、Shapefile 同名文件自动发现、PostGIS/Martin、文件地理数据库、本地文件变更监听 |
| 需要 Python sidecar | 文件地理数据库、桌面版转换工具的首选路径、依赖 rasterio 的栅格工具、AI 分割、PostGIS、Sedona |
| Mac App Store 版 | 不带 sidecar:隐藏 PostgreSQL 与 GDB 数据源、隐藏 AI 分割;Whitebox/转换/栅格/矢量工具退回 WASM;Shapefile 伙伴文件需手动多选 |
| Android / iOS | 隐藏栅格工具、转换工具、AI 分割、PostgreSQL(均依赖 sidecar);Whitebox 走 WASM 仍可用 |
| 浏览器端 | 无本地 MBTiles/GDB/PostGIS;转换输出是子集;矢量转换不收 .zip;栅格转 COG 只收 GeoTIFF;Zarr 本地文件夹在 Firefox/Safari 不可用 |
提示:判断一个功能到底在哪能用,最快的办法不是查表,而是看入口是否可用——不可用的入口是灰的,并且通常带一句原因。
5.9 坐标系、几何与字段类型的推断
5.9.1 源 CRS 的解析顺序
矢量导入通常会把已知的源 CRS 重投影到 EPSG:4326。CRS 从文件自身读出来,不是让你填的:
| 顺序 | 来源 | 适用 |
|---|---|---|
| 1 | 调用方显式指定的 overrideSourceCrs |
CAD(本身不带 CRS)等 |
| 2 | GeoParquet 的 geo 元数据块(crs 字段) |
GeoParquet |
| 3 | Parquet 原生几何列的 GEOMETRY/GEOGRAPHY 逻辑类型 |
Parquet 2.0 |
| 4 | ST_Read_Meta 的 layers[1].geometry_fields[1].crs.auth_name/auth_code |
GDAL 可读格式 |
| 5 | 同一查询里的 crs.wkt |
没有 EPSG 身份但 WKT 可用(如自定义 State Plane) |
| 6 | Shapefile 的 .prj 文本 |
元数据读取整体失败时的兜底 |
| 7 | 无 | 不做变换,坐标原样绘制 |
一个陷阱写在 crsSql 的注释里:这条查询永远读第一图层的第一几何字段,与加载器的 layer 选项无关——layer 选择的是 ST_Read 物化哪个几何,不是发现哪个图层 CRS。目前只有 CAD 会用非第一图层,而它不带 CRS,所以不影响结论;将来若出现自带 CRS 的多图层格式,这条查询需要改成按名字查。
5.9.2 几何列的识别
几何列不是靠”列名里有 geometry”猜的。识别器(detectGeometryColumn)会看:
DESCRIBE出来的列类型是否为几何类型;- GeoParquet 的
geo元数据声明的 primary 列优先于类型推断——一份文件可能有多列二进制,元数据才是权威; - 对 base64 编码的 WKB 列,抽样验证:取最多 20 个非空值,要求每一个都能被
ST_GeomFromWKB解码,才认定它是几何列。这条”全样本通过”的规则是为了避免把一个恰好叫geometry的普通属性列提升成几何。
5.9.3 无几何的 Parquet:坐标列
一份没有任何几何列、但有一对浮点列名为 lon/lat(或 longitude/latitude、lng、x/y)的 Parquet 表,会作为点图层加载,坐标假定为 WGS84。
这个能力只对 Parquet 开放(allowCoordinateColumns: isParquet)。其他格式要么自带几何,要么有自己的导入器(CSV 由用户显式选列)。理由是”发布形态”:把经纬度拆成两列的 Parquet 在数据发布里非常常见。
5.9.4 字段类型与编码
| 主题 | 行为 |
|---|---|
| CSV 字段类型 | 推断,不是声明;编号列可能被推断成数字而丢前导零 |
| DBF 编码 | 由 .cpg 决定;缺失时按默认编码解析,中文可能乱码 |
| DXF 文本 | 按 $DWGCODEPAGE 重编码(WASM GDAL 无 iconv) |
| Excel | SheetJS 读取,单元格类型由工作簿自身声明 |
| KML 样式 | 转为 simplestyle 属性(fill、fill-opacity、stroke、stroke-width、stroke-opacity、marker-color),逐要素覆盖图层样式 |
| 大整数 | Arrow → JS 转换时按行处理,超过 Number.MAX_SAFE_INTEGER 的 id 需要转字符串 |
5.10 格式 → 入口 → 限制 总表
下表按”能不能一次读完”分组。凡标注”桌面”的都只在桌面应用里可用;凡标注”sidecar”的还需要本地 Python 服务。
5.10.1 矢量与表格
| 格式 | 扩展名 | 入口 | 读取器 | 主要限制 |
|---|---|---|---|---|
| GeoJSON | .geojson .json |
Vector Layer / 拖拽 / ?data= |
JSON.parse(带 crs 时 DuckDB) |
内存膨胀数倍;大文件不推荐 |
| GeoParquet | .parquet .geoparquet |
GeoParquet Layer / Vector Layer | read_parquet |
无 geo 块时依赖逻辑类型或坐标列 |
| FlatGeobuf | .fgb .flatgeobuf |
FlatGeobuf Layer / Vector Layer | ST_Read |
—— |
| Shapefile(散) | .shp + 伙伴 |
Vector Layer / 拖拽 | shpjs | 桌面才能自动发现伙伴文件 |
| Shapefile(包) | .zip |
Vector Layer / 拖拽 | fflate + shpjs | 阈值按解压后的 .shp 计 |
| GeoPackage | .gpkg |
Vector Layer | sql.js | 多图层需选择;非 SQLite 会落回 ST_Read |
| GML | .gml |
Vector Layer | ST_Read |
未知 CRS 会报错 |
| MapInfo TAB | .tab + 伙伴 |
Vector Layer | ST_Read |
需伙伴文件可访问 |
| KML | .kml |
KML / KMZ、Vector Layer | 自研解析器 → DuckDB 兜底 | 解析器不支持时丢样式 |
| KMZ | .kmz |
KML / KMZ、Vector Layer | fflate + 自研解析器 | 远程图标不跟随重定向 |
| GPX | .gpx |
GPX Layer / 拖拽 | 纯 JS | 固定拆三层 |
| CSV / TSV | .csv .tsv .txt .dat |
Delimited Text Layer | 自研 + DuckDB | 类型推断;WKT 列走 DuckDB |
| Excel | .xlsx .xls |
Delimited Text Layer | SheetJS | 需选工作表与坐标列 |
| CAD | .dxf .dwg |
CAD Layer / 拖拽 | ST_Read |
必须手选源 CRS |
| LandXML | .xml .landxml |
LandXML Layer | 专用解析器 | 投影数据必须给源 CRS |
| OSM PBF | .osm.pbf |
OSM PBF Layer / 拖拽 | osmix(Worker) | > 50 MB 确认;5 分钟超时;不收原始 .osm XML |
| 文件 GDB | .gdb 目录 |
File Geodatabase | Python sidecar | 桌面 + sidecar;App Store 版隐藏 |
| GeoRSS | .xml .rss .atom |
GeoRSS Layer | 纯 JS | —— |
| 编码折线 | 文本 | Encoded Polyline | 纯 JS | 精度 5/6 需选对 |
| 地理标记照片 | .jpg .png .webp .heic 等 |
Geotagged Photos / 拖拽 | exifr | 无 GPS 需手动落点 |
| ICESat-2 / GEDI | .h5 |
ICESat-2 / GEDI | HDF5 读取器 | 大图元内联进工程会拖慢自动保存 |
5.10.2 栅格、瓦片与多维数组
| 格式 | 扩展名 / 来源 | 入口 | 主要限制 |
|---|---|---|---|
| GeoTIFF / COG | .tif .tiff、URL |
Raster Layer / 拖拽 | 浏览器本地读取需桌面;本地 COG 上限 2 GiB |
| PMTiles | .pmtiles、URL |
PMTiles Layer | 栅格档案在部分引擎只走原生瓦片 |
| MBTiles | .mbtiles |
MBTiles Layer | 仅桌面 |
| Zarr | 远程 store / 本地目录 | Zarr Layer | 本地目录需 File System Access API |
| NetCDF-4 / HDF5 | .nc .nc4 .cdf .h5 .hdf5 |
NetCDF / HDF | HDF4 不支持 |
| 云优化 NetCDF | Kerchunk JSON | NetCDF / HDF | 需可访问的分块 |
| MosaicJSON | .json |
读取时按需拼接 | 依赖成员资产可访问 |
| 地理配准图像 | 任意可解码图片 + GCP 表 | 专用入口 | gdal3.js 从 CDN 加载 |
5.10.3 服务与数据库
| 源 | 入口 | 主要限制 |
|---|---|---|
| XYZ | XYZ Layer | 模板方言需匹配(TMS、{-y}、{quadkey}) |
| WMS | WMS Layer | 服务需支持请求的 CRS;浏览器需 CORS |
| WMTS | WMTS Layer | 依赖服务矩阵集 |
| WFS | WFS Layer | 未知 CRS 报错 |
| WCS | WCS Layer | 仅 1.0.0;单次 ≤ 128 MB;不随平移取数 |
| OGC API - Features | 专用入口 | 默认 1000 条 |
| OGC API - Tiles | OGC Vector Tiles | 需 source-layer 名 |
| ArcGIS FeatureServer | ArcGIS Layer | 分页下载,要素多时慢 |
| ArcGIS MapServer / ImageServer | ArcGIS Layer | 设 Sublayers/Raster function 后转动态绘制 |
| CSW | CSW Catalog | 只开受支持的关联资源 |
| STAC | STAC Layer | 只加载可视化资产 |
| DuckDB | DuckDB Layer | 结果为只读,需物化才能编辑 |
| PostgreSQL / PostGIS | PostgreSQL Layer | 仅桌面 |
| SQL Server / Azure SQL | SQL Server Layer | 仅桌面;写回需先成功重读 |
| Apache Iceberg | Apache Iceberg Layer | 经 DuckDB,需表与数据文件可访问 |
5.11 本章小结
- Add Data 五个分组(Files、Web services、Cloud formats、3D layers、Databases)覆盖 42 个条目;另外四条侧路是拖拽、Browser 面板、
?data=/?style=URL 参数、插件面板。 - 矢量读取按格式分派:GeoJSON 走原生解析,GeoParquet 走
read_parquet,多数 OGR 格式走ST_Read,GeoPackage 走 sql.js,Shapefile 走 shpjs,KML 走自研解析器,OSM PBF 走 Worker 内的 osmix。 - 两个阈值决定行为:文件 ≥ 100 MB 改走 DuckDB 流式读;要素 > 100,000 会先确认再物化。
- 移交边界:GeoJSON 模式且 ≤ 100,000 要素的图层移交给 GeoLibre,获得完整 Style 面板能力;瓦片化/流式/超限的图层留在面板里。
- 栅格格式不对称:图层入口只认 GeoTIFF/COG,
.img、.vrt、.asc、.jp2、.hgt只在转换工具里可读。 - WCS 是取数不是取图:只支持 1.0.0、必须 GeoTIFF 输出、单边 1–4096 像素、单次 128 MB,且不随平移续取。
- CRS 从文件读:GeoParquet
geo块 → Parquet 逻辑类型 →ST_Read_Meta的 authority code → WKT →.prj;都没有就不变换。 - 浏览器链路有四个补丁(Parquet warm-up、
gpkg_ogr_contents、面几何 WKB 回退、.prj兜底),每一个都对应仓库里的 issue 编号。 - 平台差异是硬边界:本地 MBTiles、文件 GDB、PostGIS、SQL Server 只在桌面可用,其中后三者还依赖 sidecar。
- 引擎门控:MBTiles、高斯泼溅、Cesium ion/CZML 等条目在不同渲染引擎下可用性不同,入口会置灰并给出原因。
5.12 实践练习
-
格式侦察:取一份带中文属性的 Shapefile 压缩包,分别在”保留
.cpg“和”删除.cpg“两种情况导入,比较属性表的中文显示,并解释差异原因。 -
阈值验证:准备一份要素数明显超过 100,000 的 GeoJSON(可先用 Processing 的工具生成或合并),导入时记录确认对话框的出现时机,再把同一数据转成 GeoParquet 重新导入,比较两次的耗时与内存表现。
-
WCS 取数:用 Add Data → WCS Layer 从 USGS 3DEP 的 WCS 端点取一块你熟悉区域的高程,分别用
EPSG:4326与Automatic请求两次,比较输出像素尺寸与范围,然后导出 GeoTIFF 并用栅格样式面板调出可读的高程色带。 -
云原生链路:把一份本地 GeoJSON 依次转成 GeoParquet 与 PMTiles(Processing → GeoLibre Toolbox → Conversion),三者分别加载,记录 Layers 面板里三者的图层类型差异,并说明为什么 PMTiles 版本要素数再多也不弹 10 万要素确认。
-
引擎门控:把主图切到 Cesium,打开 Add Data 菜单,记录哪些条目被置灰,逐条写出置灰原因(可对照 5.5.5 的三个不支持集合)。
-
故障定位:构造一份故意缺少
gpkg_ogr_contents的 GeoPackage(或用脚本删除该表),观察导入过程,并说明 GeoLibre 在读取前做了哪一步修复;再构造一份坐标是投影坐标但没有geo元数据的 Parquet,说明它会画在什么位置、为什么。
延伸阅读
- 仓库文档:
docs/data-formats.md、docs/user-guide/adding-data.md、docs/tutorials/cloud-native-data.md - 源码:
apps/geolibre-desktop/src/lib/duckdb-vector-loader.ts、duckdb-vector-guard.ts、gpkg-reader.ts、geoparquet-crs.ts、add-data-renderer.ts - 项目主页:https://geolibre.app