首页 / 资讯中心 / 文章详情

GDAL OAPIF 驱动:用 OGR 接入 OGC API - Features 服务的完整实践

GDAL OAPIF 驱动:用 OGR 接入 OGC API - Features 服务的完整实践 ★ FEATURED ARTICLE
GIS遥感数据工程【免费下载链接】gdalGDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.项目地址https://gitcode.com/gh_mirrors/gd/gdal点击查看免费下载GDAL 的 OAPIFOGC API - Features驱动允许把符合 OGC API - Features 标准的在线地理空间服务当作普通的 OGR 矢量数据源来打开和查询从而在ogrinfo、ogr2ogr等命令行工具或 OGR C API 中直接访问 RESTful 服务中的要素数据。读完本文你将掌握 OAPIF 连接串的语法、各打开选项PAGE_SIZE、CRS、PREFERRED_CRS、DATETIME等的取值与默认值理解驱动如何推断图层模式、下推属性/空间/时间过滤器以及处理坐标系并能结合源码 ogroapifdriver.cpp 与测试用例 ogr_oapif.py 定位问题。驱动概述与适用前提OAPIF 驱动可以连接到任意 OGC API - Features 服务。它有一个前提假设服务分别使用 OpenAPI 3.0 描述 API、使用 JSON 承载 collection 元数据、使用 GeoJSON 编码要素集合数据。如果服务端不支持这些编码驱动将无法工作。几点背景信息来自 oapif.rst构建依赖libcurl驱动通过 CPL HTTP 接口发起请求能力支持地理参考supports_georeferencing是纯读取驱动不支持写入——从源码看OGROAPIFDriverOpen在poOpenInfo-eAccess GA_Update时直接返回nullptrogroapifdriver.cpp#L3237-L3246历史沿革在 GDAL 3.1 之前该驱动被称为 WFS3 驱动且仅支持规范的草案版本。源码至今仍兼容WFS3:前缀OGROAPIFDriverIdentify中STARTS_WITH_CI(poOpenInfo-pszFilename, WFS3:)判定为同一驱动见 ogroapifdriver.cpp#L1260-L1269测试 test_ogr_oapif_open_by_collection_and_legacy_wfs3_prefix 专门验证了这一兼容行为注册信息RegisterOGROAPIF()将其注册为连接前缀OAPIF:的矢量驱动长名称为 OGC API - Features支持 SQL 方言为OGRSQL SQLITEogroapifdriver.cpp#L3252-L3304。数据集名称语法打开一个 OGC API - Features 数据源的语法为OAPIF:http://path/to/OAPIF/endpoint其中endpoint可以是服务的 landing page着陆页也可以是/collections/{id}路径直接打开单个集合。从源码OGROAPIFDataset::Open()的实现ogroapifdriver.cpp#L1095-L1243可以看到 URL 被解析为三部分m_osRootURL服务根地址若含/collections/则截断到集合路径之前m_osServerBaseURL仅保留https://example.com部分用于解析服务返回的相对链接URL 中?之后的查询串被保存为m_osUserQueryParams之后会自动附加到每次请求上例如传递 token 等自定义参数测试 test_ogr_oapif_empty_layer_and_user_query_parameters 覆盖了这一行为。此外还有一个OAPIF_COLLECTION:内部前缀注释标明其Used by the OGCAPI driver即供 GDAL 的 OGCAPI 驱动复用 OAPIF 逻辑打开单个 collection用户一般无需直接使用该前缀。GDAL 3.10 起无需OAPIF:前缀直接打开 URL自 GDAL 3.10 起当命令行工具传入-if OAPIF选项或在 C 端调用GDALOpenEx时将papszAllowedDrivers设为仅包含OAPIF时可以直接传入不带OAPIF:前缀的 http/https URL驱动也会识别它。这一点在源码中体现为OGROAPIFDriverIdentify里的分支return STARTS_WITH_CI(poOpenInfo-pszFilename, WFS3:) || STARTS_WITH_CI(poOpenInfo-pszFilename, OAPIF:) || STARTS_WITH_CI(poOpenInfo-pszFilename, OAPIF_COLLECTION:) || (poOpenInfo-IsSingleAllowedDriver(OAPIF) (STARTS_WITH(poOpenInfo-pszFilename, http://) || STARTS_WITH(poOpenInfo-pszFilename, https://)));ogroapifdriver.cpp#L1260-L1269图层模式Layer Schema的建立机制OGR 要求每个图层具有固定 schema但 OGC API - Features Core 规范并不强制固定模式。驱动通过两条途径建立图层属性定义OGROAPIFLayer中的EstablishFeatureDefn()相关成员m_apoFieldsFromSchema、m_osDescribedByURLdescribedby关系若 collection 的 links 中提供了describedby关系的 XML Schematext/xml、application/xml或 JSON Schemaapplication/schemajson驱动会下载并解析该 schema 来确定字段。源码在图层构造函数中扫描oLinks按 media type 区分 XML/JSON schema 并记录 URLogroapifdriver.cpp#L1379-L1408测试 test_ogr_oapif_schema_from_xml_schema 与 test_ogr_oapif_schema_from_json_schema 分别验证了两种 schema 来源采样首页要素驱动会获取要素的第一页使用选定的页面大小从实际 GeoJSON 数据中推断模式。注意 GeoJSON 属性名支持嵌套路径如示例输出中的serviceType.title、pointOfContact.address.thoroughfare即嵌套对象被扁平化为以.分隔的字段名。若服务端提供的 schema 不可用或希望跳过它可以设置IGNORE_SCHEMAYES打开选项完全依赖要素采样建立模式。过滤属性、空间与时间属性过滤服务端能力探测 客户端兜底OGC API - Features Core 中只有服务端允许查询的属性子集支持等值查询可结合 AND 逻辑运算符。更复杂的请求只能在客户端部分或完全本地求值。源码层面SetAttributeFilter()ogroapifdriver.cpp#L3140-L3208的工作流程是GetQueryableAttributes()解析 OpenAPI 文档paths中 items 端点的parameters检查filter-lang参数的枚举值若声明cql-text则设置m_bHasCQLText若声明json-filter-expr则设置m_bHasJSONFilterExpression同时收集可作为查询参数的属性名即 queryable attributes。还可以从 collection links 中的queryables关系兼容 Part-3 前后的queryables/http://www.opengis.net/def/rel/ogc/1.0/queryables/[ogc-rel:queryables]三种 rel 值下载 JSON Schema取其properties排除x-ogc-role primary-geometry的几何字段作为可查询属性集合ogroapifdriver.cpp#L3043-L3134根据服务端能力选择三种下推策略之一支持 CQL-T 时把 SWQSimple Where Clause表达式树构造成 CQL 文本以filter...filter-langcql-text追加到请求 URL支持 JSON Filter Expression 时构造成filter...filter-langjson-filter-expr均不支持时退化为仅对可查询属性做等值组合的下推若整个过滤器无法下推或只有部分可下推剩余条件在客户端求值m_bFilterMustBeClientSideEvaluated并输出CPLDebug(OAPIF, Full filter will be evaluated on client side.)之类的调试信息。因此实际使用中-where name Schwelm这类简单等值条件通常能下推到服务端复杂表达式则可能需要拉取更多数据到客户端筛选。空间过滤通过SetSpatialFilter()设置的矩形空间过滤会转发到服务端。从AddFilters()实现ogroapifdriver.cpp#L1997-L2055可以看到具体拼接规则将空间过滤包络envelope拼接为bboxminX,minY,maxX,maxY查询参数17 位有效数字精度若当前激活 CRS 不是GIS 友好轴序会自动交换 X/Y 以匹配服务端要求的轴序激活 CRS 非空时追加bbox-crs与crs参数地理坐标geographic CRS下包络被钳制到 ±180/±90 范围内若等于全球范围则不添加 bbox 参数。测试 test_ogr_oapif_spatial_filter 与 test_ogr_oapif_spatial_filter_deprecated_api 覆盖了新版ISetSpatialFilter与旧版SetSpatialFilter两种 API 的 bbox 下推行为。时间过滤GDAL 3.10 起自 GDAL 3.10 起可通过DATETIME打开选项指定时间过滤。其取值应符合 OGC API - Features 规范中 Parameter datetime 一节描述的格式如2020-01-01T00:00:00Z/2020-06-01T00:00:00Z。实现上m_osDateTime在打开时被读取之后由AddFilters()以datetime...形式追加到每次 items 请求ogroapifdriver.cpp#L2045-L2053。属性过滤中的时间范围表达式如datetime ... AND datetime ...也能被识别并转换为datetime参数见 ogroapifdriver.cpp#L2531 附近 的注释 Detect expression: datetime | XXX and datetime | XXXX。测试 test_ogr_oapif_datetime_open_option 验证了该选项。CRS 支持自 GDAL 3.7 起驱动支持OGC API - Features - Part 2: Coordinate Reference Systems by Reference扩展若服务端在 collection 中报告了storageCRS属性该值将用于设置 OGR 图层的 CRS否则默认为OGC:CRS84WGS84 经纬度。源码中内置了OGC_CRS84_WKT常量ogroapifdriver.cpp#L41-L56当 bbox 未指明 CRS 时作为默认值使用与大多数 OGR 驱动一致OAPIF 驱动报告 SRS 与几何、接收空间过滤时采用GIS 友好轴序经度/东向分X在前、纬度/北向分Y在后可能覆盖权威机构authority定义的轴序。collection 的links中声明的 CRS 列表会被解析为该图层的 supported SRS 列表m_oSupportedCRSList支持通过SetActiveSRS()切换并在请求中追加crs参数。相关测试包括 test_ogr_oapif_storage_crs_easting_northing、test_ogr_oapif_storage_crs_latitude_longitude、test_ogr_oapif_storage_crs_latitude_longitude_non_compliant_server 与 test_ogr_oapif_crs_and_preferred_crs_open_options其中non_compliant_server用例专门验证了服务端未按权威轴序返回数据时的处理。图层 CRS 还可以通过下面两个打开选项控制CRS指定一个 CRS 标识符如EPSG:3067或http://www.opengis.net/def/crs/EPSG/0/3067作为图层 CRS。该 CRS必须出现在数据集各图层支持的 CRS 列表中未列出的图层将无法打开PREFERRED_CRS与CRS类似但如果某图层未列出PREFERRED_CRS则回退到默认 CRS存在storageCRS时用它否则用 EPSG:4326两者互斥同时指定会报错源码中直接返回 CRS and PREFERRED_CRS open options are mutually exclusive. 失败ogroapifdriver.cpp#L1171-L1179。打开选项参考以下打开选项在 oapif.rst 中定义并在RegisterOGROAPIF()的GDAL_DMD_OPENOPTIONLIST中注册ogroapifdriver.cpp#L3268-L3299选项类型/取值默认值说明URL字符串—OGC API - Features 服务 landing page 或指定 collection 的 URL。当用OAPIF:连接串时必填PAGE_SIZE整数最小 11000每次请求获取的要素数量。未设置时会尝试通过检查 API schema 确定服务端允许的最大页大小DeterminePageSizeFromAPI()INITIAL_REQUEST_PAGE_SIZE整数最小 120初始请求用于探测要素/建立模式获取的要素数量最大不超过PAGE_SIZEUSERPWDuserid:password—以 Basic 认证方式向远端服务器传递用户名和密码IGNORE_SCHEMAYES/NO3.1 起NO为YES时忽略服务端可能提供的 XML Schema 或 JSON SchemaCRSCRS 标识符3.7 起—用作图层 CRS必须被图层支持的 CRS 列表包含PREFERRED_CRSCRS 标识符3.7 起—与CRS相同但图层未列出该 CRS 时回退默认 CRS与CRS互斥SERVER_FEATURE_AXIS_ORDERAUTHORITY_COMPLIANT/GIS_FRIENDLYAUTHORITY_COMPLIANT若发现服务端返回的要素轴序不符合 CRS 权威定义而是GIS 友好的经度/东向在前可设为GIS_FRIENDLY。文档明确建议除非实际出现问题否则不要设置此选项DATETIME字符串3.10 起—时间过滤取值应符合 OGC API Features 规范 Parameter datetime 一节的格式几个值得注意的实现细节PAGE_SIZE默认 1000但源码默认成员值是m_nPageSize 1000同时当用户显式设置时置位m_bPageSizeSetFromOpenOptions跳过从 API schema 探测的流程ogroapifdriver.cpp#L78-L80测试 test_ogr_oapif_collection_items_page_size 与 test_ogr_oapif_initial_request_page_size 分别验证了这两条路径分页机制基于 items 响应的links中relnext链接逐页拉取collection 分页测试 test_ogr_oapif_collections_paging 覆盖了集合列表自身的分页驱动会读取响应的numberMatched等字段维护要素计数m_nTotalFeatureCount仅在无空间/属性过滤且计数已知时声明OLCFastFeatureCount能力ogroapifdriver.cpp#L3214-L3231对应测试 test_ogr_oapif_limit、test_ogr_oapif_limit_from_numberMatched。实战示例以下示例均取自官方文档 oapif.rst以https://ogc-api.nrw.de/inspire-us-feuerwehr服务为例。1. 列出服务中的类型collections$ ogrinfo OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr INFO: Open of OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr using driver OAPIF successful. 1: governmentalservice (title: Feuerwehrleitstellen) (Point)2. 查看图层概要信息含模式与范围$ ogrinfo OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr governmentalservice -al -so INFO: Open of OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr using driver OAPIF successful. Layer name: governmentalservice Metadata: DESCRIPTIONStaatliche Verwaltungs- und Sozialdienste wie öffentliche Verwaltung, ... TITLEFeuerwehrleitstellen Geometry: Point Feature Count: 52 Extent: (6.020720, 50.654901) - (9.199363, 52.300806) Layer SRS WKT: GEOGCRS[WGS 84, DATUM[World Geodetic System 1984, ELLIPSOID[WGS 84,6378137,298.257223563, LENGTHUNIT[metre,1]]], PRIMEM[Greenwich,0, ANGLEUNIT[degree,0.0174532925199433]], CS[ellipsoidal,2], AXIS[geodetic latitude (Lat),north, ORDER[1], ...], AXIS[geodetic longitude (Lon),east, ORDER[2], ...], ID[EPSG,4326]] Data axis to CRS axis mapping: 2,1 id: String (0.0) name: String (0.0) inspireId: String (0.0) serviceType.title: String (0.0) serviceType.href: String (0.0) areaOfResponsibility.1.title: String (0.0) areaOfResponsibility.1.href: String (0.0) pointOfContact.address.thoroughfare: String (0.0) ...注意Data axis to CRS axis mapping: 2,1与 WKT 中 Lat 在 ORDER[1]、Lon 在 ORDER[2] 的权威轴序——这正是前文GIS 友好轴序覆盖权威轴序说明的直观体现。3. 属性过滤服务端是否公开属性的过滤能力会决定过滤条件被部分或完全放在客户端求值$ ogrinfo OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr governmentalservice -al -q -where name Schwelm Layer name: governmentalservice Metadata: DESCRIPTION... TITLEFeuerwehrleitstellen OGRFeature(governmentalservice):1 id (String) LtS01 name (String) Schwelm inspireId (String) https://geodaten.nrw.de/id/inspire-us-feuerwehr/governmentalservice/LtS01 serviceType.title (String) Brandschutzdienst ... inGovernmentalDistrict.href (String) https://registry.gdi-de.org/id/de.nw.inspire.au.basis-dlm/AdministrativeUnit_059 POINT (7.29854802787082 51.2855116825595)4. 空间过滤$ ogrinfo OAPIF:https://ogc-api.nrw.de/inspire-us-feuerwehr governmentalservice -al -q -spat 7.1 51.2 7.2 51.5 Layer name: governmentalservice Metadata: DESCRIPTION... TITLEFeuerwehrleitstellen OGRFeature(governmentalservice):1 id (String) LtS33 name (String) Wuppertal-Solingen ... POINT (7.13806554104892 51.2674471939457)-spat minx miny maxx maxy设置的矩形空间过滤会被AddFilters()拼接为 items 请求的bbox参数下推到服务端。源码与测试索引如需进一步深入建议按以下路径阅读内容路径驱动实现约 3300 行单一文件ogroapifdriver.cpp构建定义add_gdal_driver(TARGET ogr_OAPIF ... NO_DEPS)即核心依赖由 GDAL 自带的 libcurl 相关基础设施提供CMakeLists.txtPython 自动化测试约 20 个用例用本地 mock 服务器模拟各类服务端行为ogr_oapif.py官方文档oapif.rst相关标准与文档OGC API - Features - Part 1: Core规范 17-069OGC API - Features - Part 2: Coordinate Reference Systems by Reference扩展 18-058如需基于 SOAP 的 WFS 服务请参见 WFS (1.0/1.1/2.0) 驱动文档。小结OAPIF 驱动把 RESTful 的 OGC API - Features 服务桥接到 OGR 的数据集-图层-要素模型中以OAPIF:landing page 或 /collections/{id}打开用describedbyschema 加首页采样建立模式将属性/空间/时间过滤尽可能下推到服务端CQL-T、JSON Filter Expression、bbox、datetime等参数并通过CRS/PREFERRED_CRS/SERVER_FEATURE_AXIS_ORDER等打开选项精确控制坐标系与轴序行为。理解 ogroapifdriver.cpp 中Open()、AddFilters()、SetAttributeFilter()、GetQueryableAttributes()四条主链路即可对任意接入异常模式不符、过滤未下推、轴序错误做出准确诊断。赞分享GIS遥感数据工程【免费下载链接】gdalGDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.项目地址https://gitcode.com/gh_mirrors/gd/gdal点击查看免费下载相关推荐GDAL JSONFG 驱动详解读写 OGC Features and Geometries JSONJSON-FG矢量数据GDAL JSONFG 驱动详解读写 OGC Features and Geometries JSONJSON FG矢量数据 本文围绕 GDAL 官方驱动GIS遥感数据工程GDAL/OGR HANA 驱动读取、写入与管理 SAP HANA 空间数据的完整指南GDAL/OGR HANA 驱动读取、写入与管理 SAP HANA 空间数据的完整指南 本文基于 GDAL 仓库中的 HANA 驱动文档 https://liGIS遥感数据工程yuzu Switch 模拟器三个检查点跑通游戏yuzu Switch 模拟器三个检查点跑通游戏 yuzu 是一款开源 Switch 模拟器C 编写跑在 Windows、Linux 和 AndroiGIS遥感数据工程上一篇ContraFlutterKit地图与位置功能打造用户友好的LBS应用界面下一篇如何通过AI实现自然语言驱动的3D建模从概念到落地的完整路径创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站