第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. 1.0 与 1.1 文件(含携带 covering bbox 列的版本);
  2. 2.0 文件,使用 Parquet 原生 GEOMETRY / GEOGRAPHY 逻辑类型;
  3. 几何只是 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 批次时会用后台线程,超过很小规模就会崩。

所以链路上多了三步:

  1. 先判断文件头是不是真的 SQLite(扩展名写错的文件会落回通用 ST_Read 路径);
  2. 修复缺失的 gpkg_ogr_contents(否则要素计数会让单线程 WASM 构建崩溃);
  3. 读出 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 建几何、非空间属性表。

坐标列建点的完整流程:

  1. 打开 Add Data → Delimited Text Layer,选文件或填 URL。
  2. 分隔符默认自动识别;识别不准时手动指定。
  3. 面板读出表头后,选择 经度列 与 纬度列。
  4. 指定 源 CRS(默认按 WGS84 处理);若你的坐标是投影坐标(例如某地的地方格网),必须在这里改,否则点会落在错误位置。
  5. 点击加载。结果是一个点图层,属性列来自 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。

完整流程:

  1. Add Data → WCS Layer,填入服务的 WCS 端点,点 Retrieve coverages。
  2. 选一个 coverage,然后选范围:Use view(当前视图)、Use coverage extent(coverage 自身范围),或手动输入 west / south / east / north(十进制度)。
  3. 选 Request CRS:EPSG:4326、EPSG:3857,或 Automatic。
  4. 设置输出宽高(像素),点 Add layer。
  5. 加载后用像素检视器或栅格工具处理;要留副本就 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”为例,串起本章的主要概念:

  1. 打开 Add Data → GeoParquet Layer,填入:
    https://data.source.coop/giswqs/opengeos/countries.parquet
    
  2. 勾选 Stream GeoParquet (no copy),点 Load。
  3. 图层出现在 Layers 面板;若总要素数超过 10 万,会先弹确认。
  4. 打开 Add Data → Raster Layer,填入一张 COG 的 .tif URL 并加载。
  5. 在 Style 面板 调整亮度、对比度、饱和度、色相。
  6. 若要把本地数据也变成云原生格式:Processing → GeoLibre Toolbox → Conversion → Vector to GeoParquet(浏览器端跑 DuckDB-WASM)或 Raster to COG(浏览器端跑 WebAssembly,桌面端跑 sidecar 并支持更多输入格式)。
  7. 转换完成后把产物重新加回地图验证。

提示:在浏览器构建里,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[];
}

函数内部的顺序是固定的一条流水线:

  1. 若是 .gpkg 且文件头真是 SQLite,转 loadGeoPackageVector(不走 DuckDB)。
  2. 捕获 .prj 的 CRS 文本(必须在注册文件缓冲之前,因为 registerFileBuffer 会把 ArrayBuffer 转移给 Worker)。
  3. DXF 先读 $DWGCODEPAGE(同理,注册后字节就没了)。
  4. registerVectorFileBuffers 注册文件与伙伴文件;GeoPackage 先修 gpkg_ogr_contents。
  5. ensureSpatialExtension 装 spatial 扩展(Parquet 输入要先做一次 warm-up)。
  6. 生成源 SQL:Parquet 用 read_parquet,其余用 ST_Read。
  7. DESCRIBE 出列结构 → 识别几何列。
  8. 解析源 CRS。
  9. 大要素数确认 → 执行带 ST_AsGeoJSON 的查询 → 组装 FeatureCollection。
  10. 错误分支:面几何(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)会看:

  1. DESCRIBE 出来的列类型是否为几何类型;
  2. GeoParquet 的 geo 元数据声明的 primary 列优先于类型推断——一份文件可能有多列二进制,元数据才是权威;
  3. 对 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 本章小结

  1. Add Data 五个分组(Files、Web services、Cloud formats、3D layers、Databases)覆盖 42 个条目;另外四条侧路是拖拽、Browser 面板、?data=/?style= URL 参数、插件面板。
  2. 矢量读取按格式分派:GeoJSON 走原生解析,GeoParquet 走 read_parquet,多数 OGR 格式走 ST_Read,GeoPackage 走 sql.js,Shapefile 走 shpjs,KML 走自研解析器,OSM PBF 走 Worker 内的 osmix。
  3. 两个阈值决定行为:文件 ≥ 100 MB 改走 DuckDB 流式读;要素 > 100,000 会先确认再物化。
  4. 移交边界:GeoJSON 模式且 ≤ 100,000 要素的图层移交给 GeoLibre,获得完整 Style 面板能力;瓦片化/流式/超限的图层留在面板里。
  5. 栅格格式不对称:图层入口只认 GeoTIFF/COG,.img、.vrt、.asc、.jp2、.hgt 只在转换工具里可读。
  6. WCS 是取数不是取图:只支持 1.0.0、必须 GeoTIFF 输出、单边 1–4096 像素、单次 128 MB,且不随平移续取。
  7. CRS 从文件读:GeoParquet geo 块 → Parquet 逻辑类型 → ST_Read_Meta 的 authority code → WKT → .prj;都没有就不变换。
  8. 浏览器链路有四个补丁(Parquet warm-up、gpkg_ogr_contents、面几何 WKB 回退、.prj 兜底),每一个都对应仓库里的 issue 编号。
  9. 平台差异是硬边界:本地 MBTiles、文件 GDB、PostGIS、SQL Server 只在桌面可用,其中后三者还依赖 sidecar。
  10. 引擎门控:MBTiles、高斯泼溅、Cesium ion/CZML 等条目在不同渲染引擎下可用性不同,入口会置灰并给出原因。

5.12 实践练习

  1. 格式侦察:取一份带中文属性的 Shapefile 压缩包,分别在”保留 .cpg“和”删除 .cpg“两种情况导入,比较属性表的中文显示,并解释差异原因。

  2. 阈值验证:准备一份要素数明显超过 100,000 的 GeoJSON(可先用 Processing 的工具生成或合并),导入时记录确认对话框的出现时机,再把同一数据转成 GeoParquet 重新导入,比较两次的耗时与内存表现。

  3. WCS 取数:用 Add Data → WCS Layer 从 USGS 3DEP 的 WCS 端点取一块你熟悉区域的高程,分别用 EPSG:4326 与 Automatic 请求两次,比较输出像素尺寸与范围,然后导出 GeoTIFF 并用栅格样式面板调出可读的高程色带。

  4. 云原生链路:把一份本地 GeoJSON 依次转成 GeoParquet 与 PMTiles(Processing → GeoLibre Toolbox → Conversion),三者分别加载,记录 Layers 面板里三者的图层类型差异,并说明为什么 PMTiles 版本要素数再多也不弹 10 万要素确认。

  5. 引擎门控:把主图切到 Cesium,打开 Add Data 菜单,记录哪些条目被置灰,逐条写出置灰原因(可对照 5.5.5 的三个不支持集合)。

  6. 故障定位:构造一份故意缺少 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