I. Executive Summary
The rapid adoption of Artificial Intelligence (AI) has highlighted the need for good quality training data to enable the systems to offer effective decision making support. Data quality is therefore a critical requirement for future geospatial technologies just as it has always been for historic ones. Whereas some of those future geospatial technologies will likely rely on raster data, many others will rely on vector feature data. Therefore, validators capable of checking the validity of vector feature data files are likely to play a key role in an AI-driven future.
The focus of this Engineering Report (ER) is a code sprint that was held from July 10th to 12th, 2024 to advance the support and development of open standards within the developer community. The code sprint was organized by the Open Geospatial Consortium (OGC) and hosted by Geovation in London, England. The code sprint was sponsored by Google and supported by Natural Resources Canada (NRCan). The code sprint included activities involving several OGC API Standards and data encoding standards, as well as special tracks on Data Quality & AI, Map Markup Language (MapML) and Validators. Other activities at the code sprint were related to OGC CoverageJSON, OGC SensorThings API WebSub Extension, OGC API — Records, OGC API — Features, and OGC Styles and Symbology.
The MapML special track of the code sprint sought to prototype integration of a MapML viewer into implementations of OGC API Standards. The MapML specification extends the semantics of several HTML Standard elements, and specifies a small set of new, mapping-specific elements, in the HTML namespace. This engineering report concludes that the sprint participants proved that MapML has a role to play in the geospatial ecosystem and that MapML can be easily integrated into implementations of OGC API Standards.
The Data Quality and AI track of the code sprint sought to implement support for the Training Data Markup Language for Artificial Intelligence (TrainingDML-AI) Standard and for a Data Quality Measures Register based on the ISO 19157 series of Standards. The TrainingDML-AI Standard offers a conceptual model and data encodings for geospatial machine learning training data. The engineering report concludes that the use cases for machine readable and executable provenance chains should be widened to include specific Machine Learning (ML) training data use cases. The ability to sample, correct, and train large datasets should have a reproducible method for training models.
The Validators track of the code sprint sought to extend and implement various tools for testing datasets and products for compliance to OGC Standards. In a previous code sprint a JSON-FG Linter was developed. A linter checks the correctness of code or encoding format inside an Editor application while a user is writing or editing. In this code sprint, some of the participants sought to expand on the previous work by creating a linter for OGC API — Features. Another team of participants sought to implement an Executable Test Suite (ETS) for TrainingDML-AI. The engineering report concludes that there is significant potential for client-side validators such as the Linter to enhance the developer experience, alongside server-side validators such as TEAM Engine.
The code sprint was held as a generic code sprint meaning that all OGC working groups were encouraged to participate in the event. As a result, several OGC Standards Working Groups (SWGs) set up teams of developers to collaborate with during the three-day event. In addition to providing software developers with an environment for collaborative coding and experimentation, the code sprint also provided opportunities for thought leadership through presentations and tutorials in the Mentor Stream. This made the code sprint a rich environment for knowledge transfer across teams, as well as for nurturing cross-functional teams.
The sprint participants made the following recommendations regarding potential experiments in future Collaborative Solutions and Innovation (COSI) Program initiatives:
OGC API — 3D Geovolumes experimentation in the context of Digital Twins
CDB2 experimentation in the context of Digital Twins
Experimentation on consistency of metadata frameworks
Experimentation on consistency of parameter and schema fragments in APIs
Experimentation on OGC API — Features and Geocoding
The sprint participants made the following recommendations regarding prototype development in future COSI initiatives:
Initiative on Urban Digital Twins
An activity building on the ISO metadata activity
Prototyping of an HTML MapML validator, possibly as a service. See https://github.com/Maps4HTML/validator-mapml for ideas.
Prototyping of extension of MapML to enable it to consume the JSON-based payloads that are described in the OGC API family of standards
The sprint participants made the following recommendations regarding future discussions in working groups and the Standards Program:
Discussion on consistency of parameter and schema fragments in APIs
Development of a roadmap for a possible TrainingDML-AI conformance class for OGC API — Records
Guidance on the consistency of scale between Observations, Measurements, and Samples (OMS) and the API Standards
Addition of a security element in future versions of TrainingDML-AI and other metadata encodings
Run a code sprint focused on machine-readable provenance chains, model reproducibility, and recording data quality.
Update OGC RAINBOW to offer executable code and variable injection to ensure the chains are machine readable.
Test the process of machine-readable provenance chains with several different datasets with a focus on model reproducibility.
Provide feedback to ISO/TC 211 on findings regarding Data Quality and AI.
II. Keywords
The following are keywords to be used by search engines and document catalogues.
ogcdoc, OGC document, API, openapi, html, tdml-ai, mapml, json-fg
III. Submitters
All questions regarding this document should be directed to the editors or the contributors:
Table — Submitters
| Name | Organization | Role |
|---|---|---|
| Gobe Hobona | OGC | Editor |
| Joana Simoes | OGC | Editor |
| Tom Kralidis | OSGeo | Contributor |
| Chris Little | Met Office | Contributor |
| Frank Terpstra | Geonovum | Contributor |
| Joost Farla | Geonovum | Contributor |
| Maxime Collombin | University of Applied Sciences, Western Switzerland (HEIG-VD) | Contributor |
| Sam Meek | Helyx Secure Information Systems | Contributor |
| Peter Rushforth | Natural Resources Canada | Contributor |
| Aliyan Haq | Natural Resources Canada | Contributor |
| Rui Cavaco | Norte Portugal Regional Coordination and Development Commission | Contributor |
| Ivana Ivanova | Curtin University | Contributor |
| Jerome St-Louis | Ecere | Contributor |
| Ricardo Garcia Silva | Geobeyond | Contributor |
| Samantha Lavender | Pixalytics Ltd | Contributor |
| Joan Maso | UAB-CREAF | Contributor |
| Panagiotis (Peter) A. Vretanos | CubeWerx Inc. | Contributor |
IV. Abstract
The subject of this Engineering Report (ER) is a code sprint that was held from July 10th to 12th, 2024 to advance the support and development of open standards within the developer community. The code sprint was organized by the Open Geospatial Consortium (OGC) and hosted by Geovation in London, England. The code sprint was sponsored by Google and supported by Natural Resources Canada (NRCan). The code sprint included activities involving several OGC API Standards and data encoding standards, as well as special tracks on Data Quality & Artificial Intelligence, Map Markup Language (MapML) and Validators.
1. Introduction
OGC Code Sprints experiment with emerging ideas in the context of geospatial Standards and help improve interoperability of existing Standards by experimenting with new extensions or profiles. They are also used for building proofs-of-concept to support standards development activities and the enhancement of software products. The nature of the activities is influenced by whether a code sprint is ‘generic’ or ‘focused’. All OGC working groups are invited and encouraged to set up a thread in generic code sprints, whereas focused code sprints are tailored to a specific set of standards (typically limited to three standards).
This ER presents the high-level architecture of the code sprint and describes each of the standards and software packages that were deployed in support of the code sprint. The ER also discusses the results and presents a set of conclusions and recommendations. The recommendations identify ideas for future work, some of which may be more appropriate for testbeds, pilots, or other types of OGC initiatives. Therefore, the reader is encouraged to consider the recommended future work within the context of all OGC Standards development, collaborative solutions, and innovation activities.
2. Terms, definitions and abbreviated terms
This document uses the terms defined in OGC Policy Directive 49, which is based on the ISO/IEC Directives, Part 2, Rules for the structure and drafting of International Standards. In particular, the word “shall” (not “must”) is the verb form used to indicate a requirement to be strictly followed to conform to this document and OGC documents do not use the equivalent phrases in the ISO/IEC Directives, Part 2.
This document also uses terms defined in the OGC Standard for Modular specifications (OGC 08-131r3), also known as the ‘ModSpec’. The definitions of terms such as standard, specification, requirement, and conformance test are provided in the ModSpec.
For the purposes of this document, the following additional terms and definitions apply.
An Application Programming Interface (API) is a standard set of documented and supported functions and procedures that expose the capabilities or data of an operating system, application, or service to other applications (adapted from ISO/IEC TR 13066-2:2016).
A coordinate system that is related to the real world by a datum term name (source: ISO 19111).
A document (or set of documents) that defines or describes an API. An OpenAPI definition uses and conforms to the OpenAPI Specification (https://www.openapis.org).
An API using an architectural style that is founded on the technologies of the Web [source: OGC API — Features — Part 1: Core].
2.5. Abbreviated terms
API
Application Programming Interface
CITE
Compliance Interoperability & Testing Evaluation
CRS
Coordinate Reference System
EDR
Environmental Data Retrieval
GIS
Geographic Information System
OGC
Open Geospatial Consortium
OWS
OGC Web Services
REST
Representational State Transfer
TEAM
Test, Evaluation, And Measurement Engine
3. High-Level Architecture
As illustrated in Figure 1, the sprint architecture was designed to enable client applications to connect to different servers that implement a variety of standards. The architecture also included several different software libraries that support open geospatial standards and enable the extraction, transformation, and loading of geospatial data. The participants deployed the their software in their own infrastructure.
Figure 1 — High Level Overview of the Sprint Architecture
The rest of this section describes the software deployed, and standards implemented during the code sprint or in support of the code sprint.
3.1. Approved OGC Standards
3.1.1. OGC SensorThings API
The OGC SensorThings API Standard provides an open and harmonized way to interconnect devices, applications, and data over the web and on the Internet of Things (IoT) (OGC 18-088). At a high level the SensorThings API provides two main parts, namely Part I — Sensing, and Part II — Tasking. The Sensing part of the Standard provides a way to manage and retrieve observations and metadata from different sensor systems. The Tasking part of the Standard provides a way for tasking IoT devices, such as actuators and sensors. The SensorThings API follows REST principles and uses JSON for encoding messages as well as Message Queuing Telemetry Transport (MQTT) for publish/subscribe operations.
In this code sprint, activity related to the OGC SensorThings API focused on a WebSub extension to the OGC SensorThings API Standard. The OGC SensorThings API Extension WebSub prototype is based on the W3C WebSub Recommendation. The prototype supports subscribe/unsubscribe and opaque discovery capabilities that are offered by implementations of OGC SensorThings API.
3.1.2. OGC API — Features
The OGC API — Features Standard offers the capability to create, manage, and query spatial data on the Web. The Standard specifies requirements and recommendations for Web APIs that are designed to facilitate the sharing of feature data. The specification is a multi-part standard. Part 1, labelled the Core, describes the mandatory capabilities that every implementing service has to support and is restricted to read-access to spatial data that is referenced to the World Geodetic System 1984 (WGS 84) Coordinate Reference System (CRS) (OGC 17-069r4). Part 2 enables the use of different CRSs, in addition to the WGS 84 (OGC 18-058r1). Additional capabilities that address specific needs will be specified in additional parts. Envisaged future capabilities include, for example, support for creating and modifying data, more complex data models, and richer queries.
3.1.3. OGC API — Tiles
OGC API — Tiles specifies a Standard for Web APIs that provide tiles of geospatial information (OGC 20-057). The Standard supports different forms of geospatial data, such as tiles of vector features (colloquially called “vector tiles”), coverages, maps (or imagery), and potentially eventually additional types of tiles of geospatial data.
Vector data represents geospatial objects such as points, lines, and polygons. Tiles of vector feature data (i.e., ‘vector tiles’) represent partitions of vector data covering an area (e.g., lines representing rivers in a country).
In this context, a map is essentially an image representing at least one type of geospatial information. Tiles of maps (i.e., map tiles) represent subsets of maps covering an area.
3.1.4. OGC API — Environmental Data Retrieval
The OGC API — Environmental Data Retrieval (EDR) Standard provides a family of lightweight interfaces to access Environmental Data resources. Each resource addressed by an EDR API maps to a defined query pattern. This Standard identifies resources, captures compliance classes, and specifies requirements which are applicable to OGC Environmental Data Retrieval API’s. This Standard addresses both discovery and query operations. Discovery operations enable the API to be interrogated to determine its capabilities and retrieve metadata about the published resource. Query operations allow Environmental Data resources to be retrieved from the underlying data store based upon simple selection criteria, defined by this standard and selected by the client.
Version 1.1 of OGC API — EDR has been published (OGC 19-086r6). The EDR API Standards Working Group (SWG) has recently obtained approval to publish Part 2 of the Standard: “OGC API — Environmental Data Retrieval — Part 2: Publish-Subscribe workflow” (OGC 23-057). The focus of the EDR API-related work in this code sprint is therefore on the use of Part 2 of the Standard. Work continues on defining improvements to Part 1: Core Version 1.1 to be known as Version 1.2.
3.1.5. OGC API — Processes
The OGC API — Processes Standard supports the wrapping of computational tasks into executable processes that can be offered by a server through a Web API and be invoked by a client application (OGC 18-062r2). The Standard enables the execution of computing processes and the retrieval of metadata describing the purpose and functionality of the processes. Typically, these processes execute well-defined algorithms that ingest vector and/or coverage data to produce new datasets.
The OGC API — Processes — Part 2: Deploy, Replace, Undeploy candidate Standard extends the core capabilities specified in the OGC API — Processes — Part 1: Core (OGC 18-062r2) with the ability to dynamically add, modify and/or delete individual processes using an implementation (endpoint) of the OGC API — Processes Standard.
3.1.6. Training Data Markup Language for Artificial Intelligence
The Training Data Markup Language for Artificial Intelligence (TrainingDML-AI) is a Standard for describing Machine Learning Training Datasets and their quality, as well as how they have been developed. Version 1.0 of the Part 1: Conceptual Model Standard has been published. Parts 2 & 3 with JSON and XML encodings have been submitted to OGC.
3.1.7. OGC CoverageJSON
CoverageJSON is a format for encoding coverage data such as grids, time series, and vertical profiles, each distinguished by the geometry of their spatiotemporal domain. A CoverageJSON document is serialized in JavaScipt Object Notation (JSON). A CoverageJSON object represents a domain, a range, a coverage, or a collection of coverages. A range in CoverageJSON represents coverage values. A coverage in CoverageJSON is the combination of a domain, parameters, ranges, and additional metadata. A coverage collection represents a list of coverages.
3.2. Candidate OGC Standards
3.2.1. OGC API — Connected Systems
The OGC API — Connected Systems candidate Standard specifies the fundamental API building blocks for interacting with Connected Systems and associated resources (OGC 20-058). A Connected System represents any kind of system that can either directly transmit data via communication networks (being connected to them in a permanent or temporary fashion), or whose data is made available in one form or another via such networks. This definition encompasses systems of all kinds, including in-situ and remote sensors, actuators, fixed and mobile platforms, airborne and space-borne systems, robots and drones, and even humans who collect data or execute specific tasks.
3.2.2. OGC API — Maps
The OGC API — Maps candidate Standard describes an API that can serve spatially referenced and dynamically rendered electronic maps (OGC 20-058). The specification describes the discovery and query operations of an API that provides access to electronic maps in a manner independent of the underlying data store. The query operations allow dynamically rendered maps to be retrieved from the underlying data store based upon simple selection criteria as defined by the client.
3.2.3. OGC API — Records
The OGC API — Records candidate Standard provides discovery and access to metadata records that describe resources such as features, coverages, tiles / maps, models, assets, datasets, services, or widgets (OGC 20-004). The candidate Standard enables the discovery of geospatial resources by standardizing the way collections of descriptive information about the resources (metadata) are exposed. The candidate Standard also enables the discovery and sharing of related resources that may be referenced from geospatial resources or their metadata by standardizing the way all kinds of records are exposed and managed.
3.2.4. OGC API — Discrete Global Grid Systems
The OGC API — Discrete Global Grid Systems candidate Standard defines building blocks which can be used as part of a Web API to retrieve geospatial data for a specific area, time and resolution of interest, based on a specific Discrete Global Grid System (DGGS) and indexing scheme (OGC 21-038). The candidate Standard also supports querying of the list of DGGS zones from which data is available.
3.2.5. OGC Features and Geometries JSON (JSON-FG)
The draft OGC Features and Geometries JSON (JSON-FG) Standard extends the GeoJSON format to support a limited set of additional capabilities that are out-of-scope for GeoJSON but that are important for a variety of use cases involving feature data (OGC 21-045r1). In particular, the JSON-FG Standard specifies the following extensions to the GeoJSON format:
the ability to use Coordinate Reference Systems (CRSs) other than WGS84;
support for solids and prisms as geometry types;
the ability to encode temporal characteristics of a feature; and
the ability to declare the type and the schema of a feature.
3.2.6. DGGS-JSON and DGGS-UBJSON
The DGGS-JSON and DGGS-UBJSON (based on Universal Binary JSON) formats, defined as part of requirement classes for OGC API — DGGS, provide a compact and efficient way to retrieve data quantized to a particular Discrete Global Grid Reference System (DGGRS). By leveraging a shared knowledge of the DGGRS between the client and server (or the producer and consumer in the case of an offline file), the large majority of the payload is simply the data values associated with each sub-zone at a given relative depth of the parent zone for which data is being encoded. A fixed deterministic sub-zone order needs to be defined as part of the DGGRS in order to enable this.
A draft JSON schema for DGGS-JSON is available. See also the first implementation deployed in the GNOSIS Map Server during this code sprint.
3.2.7. OGC Cartographic Symbology candidate Standard
The OGC Cartographic Symbology candidate Standard (CartoSym) defines a Conceptual Model, a Logical Model and Encodings for describing symbology rules for the portrayal of geographical data (OGC 18-067r4). The targets of this candidate Standard are symbology encodings and cartographic rendering engines. The candidate Standard is modularized into multiple requirements classes, with a minimal core describing an extensible framework, with clear extension points, for defining styles consisting of styling rules selected through expressions and applying symbolizers configured using properties. The candidate Standard defines two encodings for the logical model: one based on JSON which can be readily parsed by JSON parsers, as well as a more expressive encoding better suited for hand-editing inspired from Web Cartographic Styled Sheets (CSS) and related cartographic symbology encodings.
3.3. Specifications from the Community
3.3.1. MapML
3.3.1.1. Introduction
Map Markup Language (MapML) is a text-based format which enables web page authors to insert maps into web pages as hypertext documents exchanged over HTTP. One of the well known implementations of MapML is the open source GeoServer software product, which provides access to MapML through WMS, WMTS and WFS so far. Through this code sprint, the MapML community sought to tackle integration of MapML into OGC APIs and potentially to demonstrate both the serving of MapML documents through such APIs and the accessing of content encoded as MapML. Experimenting with the implementation of MapML in OGC APIs is important because of the need to obtain feedback from the developer community and because MapML is a proposal to the browser community from the spatial community for natively integrating maps into web pages. In order to make that case to the browser community, there is a need to have the widest possible review and feedback from the geospatial community.
Across society, HTML plays a key role on the Web. Maps are therefore important enough to fit into web browsers because maps play a key role in how location is communicated across society. So on the day that browsers handle maps natively the same way that they handle images, there should be a wealth of content waiting to be displayed on the possibly billions of web pages that will display location information. Thus, integrating MapML support into geospatial content management systems that are fronted by implementations of OGC Web Service Standards and OGC API Standards will be essential and so the OGC community and the MapML viewer polyfill are key to meeting that goal.
3.3.1.2. Structure
The MapML viewer is a media-like widget that can be controlled with attributes like other forms of media that can be embedded in a web page. The Map content is represented by the layer element and it comes in two flavors, inline and remote, shown in Figure 2 on the left and right respectively. Inline content is interactive and has a Document Object Model (DOM) footprint in the web browser. In contrast, remote content can be identified by the fact that the layer has a source src attribute pointing to a remote web service or OGC API. Remote content is essential to enabling mashups of ad hoc content from around the Web, and would be provided by OGC APIs directly.
Figure 2 — The structure of MapML
Inline content in MapML comes in the form of map-extent, map-feature, map-tile elements, as well as various forms of metadata, and all inline content is encoded according to the HTML syntax parser rules within layer- elements. Remote content is loaded via content fetched from the layer- src attribute, and is encoded in the XHTML namespace, and because XML parsing rules apply, it is naturally more rigid. However because it is XHTML, it can be readily incorporated into HTML pages.
Map extents (map-extent elements) represent templated tiled, feature, or image map content that is repeatedly fetched as needed, based on movement of the map viewer. Map features are of course OGC Simple Features and tiles are either feature- or image-based. Geospatial data can be viewed in a web page as one or more maps on the document canvas in a single or multi page web application, by using the MapML viewer element as many times as needed.
The viewer is conceptually like the video or audio element. It has a set of built-in controls that are exemplified in Figure 3, and they can be turned on or off as a group or individually. The default controls are keyboard accessible and are navigable with Tab and Shift+Tab keys. The default controls are not styleable, so if custom controls are needed, then a developer has to create their own. That is why the controls are toggleable.
Figure 3 — MapML Viewer
3.3.1.3. Layers
In MapML, a map can have zero or more layers and for map layers fewer is oftentimes better, because a map can get very visually cluttered if it has too many layers. Layers are exposed to the user through the layer control in DOM order, from the closest to document start to the furthest. MapML documents are parsed in sequence based on ‘distance’ from the document start. Layers and layer content is rendered according to the ‘painters model’. Layers contain a single level of node depth; there cannot be recursively or infinitely nested layers or layer content.
3.3.1.4. Map Extents
A map extent (map-extent element) is a templated form of map content that allows the map author to fetch features, tiles or whole-map image content on demand (from a web service or API) based on map movement. The fetched content overlays and potentially obscures previously rendered content (per the painter’s model). Consequently, each map-extent is exposed in the layer control underneath the parent layer as part of that layer’s settings menu item, in which it is labeled (by default) as a ‘Sub-layer’ (the default accessible name) which can be progressively turned on or off by the user, whereas individual features are not exposed individually in the layer control. If control of individual features is needed, those features need to be wrapped in a layer of their own. Layers can contain feature collections. Features on a map are a single tab stop, but are keyboard navigable via the arrow keys.
3.3.1.5. Coordinate Reference Systems
MapML supports different map tiling schemes through a concept called the Tiled Coordinate Reference System (TCRS) A TCRS is a set of associated coordinate systems (some of) which share a common origin in space, but which differ by the size of their smallest unit at defined locations, e.g. meters/pixel along the equator (MapML). A TCRS binds an instance of a Coordinate Reference System with an instance of a Tile Matrix Set into a single well known value of projection, and it places axis order constraints on content encoded according to that TCRS (as do all CRS). Specifically, coordinates when not explicitly marked up, are required to be encoded with horizontal axis followed by vertical axis (“xy” order). An example of how the TCRS may be handled can be observed in GeoServer which defines the “MapML:” CRS authority for the pre-defined MapML projection values (i.e. MapML:OSMTILE, MapML:CBMTILE, MapML:WGS84 and MapML:APSTILE) in which the association between the tile matrix set and the coordinate reference system of the given TCRS is managed internally. Using this authority prefix allows GeoServer to enable MapML access through the strict OGC web service interface standards, and a similar technique may be applicable in the OGC API implementations. There are the four well known or proof of concept TCRS defined by the MapML specification (most importantly: OSMTILE, WGS84, and CBMTILE), and web developers can define custom TCRS for use in the MapML viewer, using the proj4.js library. OGC API implementations might be able to adapt the GeoServer technique of defining the “MapML:” CRS authority for OGC API-based interfaces where an official spatial reference system name is a required information item, and in doing so, to not rely on unwritten semantics which commonly happens in geospatial information exchange.
3.3.2. ISO 19157-3 Data Quality Measures Register
Concepts around data quality have evolved over the past 20 or so years with the advent and proliferation of open sourced, non-authoritative data sources. Standards such as ISO 19115 Geospatial Metadata and ISO 19157 Geospatial Data Quality have been used and incorporated into metadata profiles to record the quality of geospatial datasets. One of the grounding concepts within the ISO standards is the universe of discourse which is poorly translated to ground truth or real world. In the early days of ISO concepts of data quality, the universe of discourse was much more simple to determine because the authoritative datasets were routinely ground truthed for accuracy. A salient example of this is aerial photography where flight paths were planned and a ground crew would lay out tie points on the ground to be captured by the imagery. Distances then could be physically measured to create an overall positional accuracy for the image. In the modern world of non-authoritative, crowdsourced or open source data, the universe of discourse concept does not apply in the same way. The data quality model reports on concepts such as:
Completeness — the number or percentage of features that appear within the dataset compared to the universe of discourse.
Thematic Accuracy — the number or percentage of misclassified features.
Logical Consistency — the number of missing links in a road dataset.
Conceptual Consistency — number of overlapping surfaces in a dataset.
To facilitate dataset comparisons, there is a need for evaluations and data quality reports (metadata or a quality evaluation report) to be expressed in a comparable way. Furthermore, it is necessary to have a common understanding of the data quality measures that have been used. An example of such common understanding of a standard quality measure is defined in ISO 19157-1:2023 Geographic information — Data quality — Part 1: General requirements (ISO 19157-1:2023). This standard defines the structure of a data quality measure as well as all additional attributes describing a data quality measure — see in Figure 4.
Figure 4 — Structure of a data quality measure as defined in ISO 19157-1:2023
To comply with current best practice for sharing data over the web, these measures have to reside in a machine-actionable data quality measures register. Such a register is currently under development at ISO/TC211 and OGC. ISO 19157-3 Geographic information — Data quality — Part 3: Data quality measures register will be the standard defining the components and content structure of a register for data quality measures, and the registration and maintenance procedure (ISO/AWI 19157-3). All of this is in compliance with ISO 19135 Geographic information — Registration and registration procedures, a governing standard for all ISO/TC211 registers (ISO 19135-1:2015). The measures will be published through the ISO 19157-3 register which will be hosted at OGC, the Registration Authority of ISO 19157-3. OGC will host the ISO 19157-3 register on OGC RAINBOW, a registry of terms and definitions. The full version of the ISO 19157-3 Data Quality measures register is expected to be published together with the ISO 19157-3 standard in early 2026.
3.4. Software Projects and Products
3.4.1. CREAF Miramon
The Centre for Ecological Research and Forestry Applications (CREAF) at the Autonomous University of Barcelona (UAB) deployed an instance of the MiraMon Map Server. The actual instance is available here and provides a single collection with a well known bathymetry dataset called ETopo2 as the single collection. The MiraMon Map Server is a CGI application that runs on IIS and supports several OGC standards including OGC API — Maps, OGC API — Tiles, Web Map Service (WMS), and Web Map Tile Service (WMTS). The CGI is developed in pure C language and available as a free software.
3.4.2. QGIS
QGIS is a free and open-source cross-platform desktop GIS that supports viewing, editing, and analysis of geospatial data. The QGIS stable release V3.28.6-Firenze, and later versions, has a Time Slider/Controller added to the menu bar. It behaves like a video controller if relevant to the data being displayed. This and later versions also support the OGC API-EDR queries via a plugin.
Release V3.37 and later now supports a Vertical Slider for data and layers that have a vertical extent.
Figure 5 — Screenshot of QGIS Time Controller
Figure 6 — Screenshot of QGIS EDR Plugin menu
3.4.3. Status of OGCAPI SourceType support in QGIS
QGIS supports adding a Raster or Vector Layer, using an OGC API Source Type. Under the hood, QGIS uses the OGCAPI GDAL driver. During this code sprint, this functionality was tested for different OGC APIs, in order to figure out what is working and to try to understand if the issue is on GDAL or QGIS.
An issue with relative links was identified on GDAL, which was affecting all the APIs. The issue was already fixed and is described here.
The current status (using QGIS version 3.39.0-Master QGIS code revision 399f7df1c7 and GDAL/OGR version 3.10.0dev-126a88523a) is:
Figure 7 — Screenshot an OGCAPI - Maps collection from Gnosis on QGIS
Figure 8 — Screenshot an OGCAPI - Maps collection from pygeoapi on QGIS
Figure 9 — Screenshot an OGCAPI - Tiles (raster) collection on QGIS
Figure 10 — Screenshot an OGCAPI - Coverages collection on QGIS
More details about the setup for testing this functionality can be found on this issue.
3.4.4. Geonovum JSON Linter
The Geonovum JSON Linter is a validation tool that has been designed to support testing and checking of JSON-encoded files. The tool runs in a web browser and is implemented using NodeJS. The tool is extensible to enable it to validate conformance to different formats, as well as to support the checking of requests and responses from Web APIs.
3.4.5. OSGeo pygeoapi
pygeoapi is a Python server implementation of the OGC API suite of Standards. The project emerged as part of the next generation OGC API efforts in 2018 and provides the capability for organizations to deploy a RESTful OGC API endpoint using OpenAPI, GeoJSON, and HTML. pygeoapi is open source and released under an MIT license. pygeoapi is an official OSGeo Project as well as an OGC Reference Implementation. pygeoapi supports numerous OGC API Standards. The official documentation provides an overview of all supported standards.
3.4.6. OSGeo pygeometa
pygeometa provides a lightweight and Pythonic approach for users to easily create geospatial metadata in standards-based formats using simple configuration files called Metadata Control Files (MCF). The software has minimal dependencies (the installation is less than 50 kB), and provides a flexible extension mechanism leveraging the Jinja2 templating system. Leveraging the simple but powerful YAML format, pygeometa can generate metadata in numerous standards. Users can also create their own custom metadata formats which can be plugged into pygeometa for custom metadata format output. pygeometa is open source and released under an MIT license.
For developers, pygeometa provides a Pythonic API that allows developers to tightly couple metadata generation within their systems and integrate nicely into metadata production pipelines.
The project supports various metadata formats out of the box including ISO 19115, the WMO Core Metadata Profile, and the WIGOS Metadata Standard. The project also supports the OGC API — Records core record model as well as STAC (Item).
3.4.7. OSGeo OWSLib
OWSLib is a Python client for OGC Web Services and their related content models. The project is an OSGeo Community project and is released under a BSD 3-Clause License.
OWSLib supports numerous OGC standards, including increasing support for the OGC API suite of standards. The official documentation provides an overview of all supported standards.
3.4.8. ldproxy
ldproxy is an implementation of the OGC API family of Standards, available under the MPL 2.0 open source license. ldproxy is developed by interactive instruments GmbH, written in Java, and is deployed using Docker containers. ldproxy implements all parts of OGC API — Features, OGC API — Tiles, OGC API — Styles, OGC API — 3D GeoVolumes, and OGC API — Routes. ldproxy is an OGC Reference Implementation for Parts 1 and 2 of OGC API — Features.
3.4.9. CubeWerx Geospatial Data Server
The CubeWerx Geospatial Data Server (“cubeserv”) is implemented in C and currently implements the following OGC Standards and draft specifications.
Multiple conformance classes and recommendations of the OGC API — Tiles — Part 1: Core Standard
Multiple conformance classes and recommendations of the OGC API — Maps — Part 1: Core candidate Standard
All conformance classes and recommendations of the OGC API — Features — Part 1: Core Standard
Multiple conformance classes and recommendations of the OGC API — Records — Part 1: Core candidate Standard
Multiple conformance classes and recommendations of the OGC API — Coverages — Part 1: Core candidate Standard
Multiple conformance classes and recommendations of the OGC API — Processes — Part 1: Core Standard
Multiple versions of the Web Map Service (WMS), Web Processing Service (WPS), Web Map Tile Service (WMTS), and Web Feature Service (WFS) Standards
A number of other “un-adopted” OGC Web Service draft specifications including the Testbed-12 Web Integration Service, OWS-7 Engineering Report — GeoSynchronization Service, and the Web Object Service prototype
The cubeserv executable supports a wide variety of back ends including Oracle, MariaDB, SHAPE files, etc. It also supports a wide array of service-dependent output formats, for example, Geography Markup Language (GML), GeoJSON, Mapbox Vector Tiles, MapMP, as well as several coordinate reference systems.
3.4.10. GNOSIS Map Server
The GNOSIS Map Server is written in the eC programming language and supports multiple OGC API Standards. GNOSIS Map Server supports multiple encodings including GNOSIS Map Tiles (which can contain either vector data, gridded coverages, imagery, point clouds, or 3D meshes), Mapbox Vector Tiles, GeoJSON, GeoTIFF, GML, and MapML. An experimental server is available online at https://maps.gnosis.earth/ogcapi and has been used in multiple OGC Innovation Program initiatives.
3.4.11. OpenSensorHub
OpenSensorHub is an open source software product for supporting web-enabled access to a variety of sensor systems (from the simple to the more complex). OpenSensorHub implements the OGC Sensor Web Enablement (SWE) Standards, as well as the OGC SensorThings API. OpenSensorHub also implements the OGC API — Connected Systems candidate Standard.
3.4.12. OGC TEAM Engine
The Test, Evaluation, And Measurement (TEAM) Engine is a testing facility that executes test suites implemented using the TestNG framework or the OGC Compliance Test Language (CTL). It is typically used to verify specification compliance and is the official test harness of the OGC Compliance & Interoperability Testing & Evaluation (CITE) program. TEAM Engine is able to import Executable Test Suite (ETS) libraries that are implemented using the TestNG and CTL. Each ETS is implemented to execute source code that reflects the test methods specified in the Abstract Test Suite (ATS) that is specified in an associated OGC Standard. For the this code sprint, the TEAM Engine activity focused on implementing an initial ‘alpha’ version of the OGC Training Data Markup Language for Artificial Intelligence (TrainingDML-AI) Part 2: JSON Encoding candidate Standard.
3.4.13. OGC RAINBOW
OGC RAINBOW is a Web accessible source of information about things (’Concepts’) the OGC defines or that communities ask the OGC to host on their behalf. It applies FAIR principles to the key concepts that underpin interoperability in systems using OGC specifications. It can be accessed at https://www.opengis.net/def and holds definitions for terms defined by OGC processes, along with a range of ‘metamodel’ resources geospatial community uses to describe and interconnect these resources. There are a number of different types of resource (all linked together to support the ‘Findable’ principle of FAIR). In this code sprint, RAINBOW was specifically used in support of discovery and access to Coordinate Reference System (CRS) definitions and the prototype ISO 19157-3 Data Quality Measures Register.
4. Results
The code sprint included multiple software applications and experimented with several standards. This section presents the key results from the code sprint.
4.1. Approved OGC Standards
4.1.1. OGC CoverageJSON
CoverageJSON maintainers participated in the code sprint with a focus on identifying potential avenues for enhancing the CoverageJSON ecosystem. The code sprint offered a useful forum for discussion and experimentation across various working groups. Therefore, where one solution was found to be useful for one standard, there was a high likelihood that the same solution (or a modification of it) could be useful to another.
Some of the potential opportunities for CoverageJSON identified during the code sprint included:
Registration of a media type application/cov+json with Internet Assigned Numbers Authority (IANA).
Migration from an OGC Community Standard to a full OGC Standard.
Improvement of the CoverageJSON ecosystem through GDAL and STAC Browser support, as well as through implementation of a Python-based validator.
Addition of CoverageJSON to the OGC Developer Website.
4.1.2. Training Data Markup Language for Artificial Intelligence
At the time of the code sprint, the Training Data Markup Language for Artificial Intelligence (TrainingDML-AI) Conceptual Model was a fully approved OGC Standard. However, both the JSON and XML encodings of TrainingDML-AI were still candidate Standards. Therefore, several of the code sprint activities involved TrainingDML-AI data encodings. Furthermore, the TrainingDML-AI Standard was the focus of a mentoring session.
Another sprint activity involved configuring a training dataset as a pygeometa metadata control file and generating TrainingDataML-AI metadata from pygeometa. A more detailed description of the pygeometa activities is documented at Clause 4.4.2. This capability potentially makes it possible to conduct Extract-Transform-Load operations between other metadata formats supported by pygeometa and the JSON encoding on TrainingDML.
The feedback provided by sprint participants also enabled the SWG members from Wuhan University (WHU) to fix issues encountered in example files for the candidate Standard. Furthermore, the SWG members also participated in the discussions and supported the implementations by fellow sprint participants, which included:
Pixalytics Ltd (Sam Lavender) worked on updating their implementation, using the pytdml Python library. Problems were faced with recent updates to the library and so an issue was raised.
TEAM Engine maintainers from OGC Staff worked on an Executable Test Suite (ETS) which will be integrated into OGC’s compliance testing tools, in the future, to provide compliance testing of TrainingDML-AI datasets. A screenshot of TEAM Engine is shown in Figure 11.
Figure 11 — Screenshot of the TEAM Engine user interface with TrainingDML test results
4.2. Candidate OGC Standards
4.2.1. OGC SensorThings API WebSub Extension
One objective of the EU CitiObs project is to provide decision makers with fit-for-purpose information about air quality collected from different base systems. Currently, each system collects data from sensors using proprietary APIs but makes the data available (to project partners) and the CitiObs decision support system via STAplus. STAplus, the OGC SensorThings API PLUS extension defines additional entities in the data model that support the sensor data management for Citizen Science.
When building such a decision support system, two important functional requirements have to be considered:
Fetching sensor data via STAplus using modern clients like Orange or Jupiter Notebook. The Orange plugin is currently in development, but for managing sensor data via SensorThings API or STAplus, the first version of a Python library is available on PyPi: STAplus on PyPi.
Receiving updates of sensor readings based on self-set criteria. To support this requirement, the CitiObs team has started to develop (yet another) extension to SensorThings API: The WebSub Extension.
This section of the Code Sprint Engineering Report introduces the WebSub extension and illustrates the current state of the implementation.
The SensorThings API WebSub Extension candidate Standard is currently in development. The idea of this extension was presented to the OGC membership during the 2024 Delft and Montreal meetings. There seems to be great interest in the functionality of the WebSub Extension which sparked the idea to contribute to the 2024 Code Sprint in London and improve the current prototype.
4.2.1.1. Introduction to SensorThings API WebSub Extension
The OGC SensorThings API Extension WebSub is based on the W3C WebSub Recommendation. In particular the WebSub API for subscribe/unsubscribe and the opaque discovery via link data headers make the WebSub extension potentially applicable to other OGC APIs.
The idea behind WebSub, as illustrated in WebSub — High Level Protocol Flow is quite simple: A Subscriber uses a service’s synchronous API to fetch data. If interested in receiving event driven data via a provided WebHook, the subscriber can use the Link rel='self' to subscribe for updates. The subscription requires that the subscriber provides a callback URL which is a regular HTTP(S) POST endpoint that conforms to the W3C Recommendation.
The Publisher is a SensorThings API implementation that implements the WebSub extension. The requirement is that the implementation returns the Link headers role='self' and role='hub' for an HTTP GET and HEAD request. The HTTP HEAD request can be used by the subscriber if only interested in the WebSub discovery without fetching data.
A SensorThings API WebSub Hub implementation uses the SensorThings MQTT functionality to subscribe for updates. Any SensorThings API service deployment that offers the Link rel='hub' header must support MQTT notifications as defined in the SensorThings API Requirement Classes of the OGC SensorThings API Part 1: Sensing Version 1.1 Standard:
SERVICE_VERSION/RESOURCE_PATH/COLLECTION_NAME as defined in Clause 14.2.1 can be extended with a ? followed by an ODATA query — e.g. v1.1/Datastreams(1)/Observations?$filter=result gt 30
SERVICE_VERSION/RESOURCE_PATH_TO_AN_ENTITY as defined in Clause 14.2.2 can be extended with a ? followed by an ODATA query — e.g. v1.1/Observations?$select=result
SERVICE_VERSION/RESOURCE_PATH_TO_AN_ENTITY/PROPERTY_NAME as defined in Clause 14.2.3 — e.g. v1.1/Observations/result
4.2.1.2. WebSub Extension Implementation (SensorThings API Service)
A SensorThings API Service must support the W3C WebSub discovery. This functionality was implemented as a plugin to the FROST-Server that will be made available in a public GitHub repository once the WebSub extension idea has matured. For testing purposes, the plugin is deployed on the CitiObs STAplus test endpoint.
curl --head https://citiobs.demo.secure-dimensions.de/staplus/v1.1/Observations
return the following HTTP headers
HTTP/2 200
server: nginx/1.27.0
date: Mon, 15 Jul 2024 07:35:00 GMT
content-type: application/json;charset=UTF-8
content-length: 0
link: <https://hub.demo.secure-dimensions.de/>; rel="hub"
link: <https://citiobs.demo.secure-dimensions.de/staplus/v1.1/Observations>; rel="self"
4.2.1.3. WebSub Extension Implementation (Hub)
The Hub implementation’s functionality is described in the W3C WebSub Recommendation. The SensorThings specific aspect is that the Hub uses MQTT to subscribe to the SensorThings API service. The Hub must derive the MQTT topic from the URL received via the subscription API. Basically, the Hub removes the SensorThings rootURL as advertized in the SensorThings API service’s landing page. As an example, the link: <https://citiobs.demo.secure-dimensions.de/staplus/v1.1/Observations>; rel="self" transforms into the MQTT topic v1.1/Observations.
The Hub associates the MQTT notifications to the callback URL provided with the subscription request. For example, the following subscription request triggers the Hub to link the MQTT topic v1.1/Observations with callback (Webhook) URL https://webhook.site/e40fa5de-239b-4dd6-a0dd-25e50f805d4e:
curl --location 'https://hub.demo.secure-dimensions.de/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'hub.mode=subscribe' \
--data-urlencode 'hub.topic=https://citiobs.demo.secure-dimensions.de/staplustest/v1.1/Observations' \
--data-urlencode 'hub.callback= https://webhook.site/e40fa5de-239b-4dd6-a0dd-25e50f805d4e' \
--data-urlencode 'hub.secret=this is a good secret :)' \
--data-urlencode 'hub.callback.x_api_key=this is a good key :)'
To link the callback with the topic, the implementation can use Redis for example:
let client = redis.createClient();
let key = md5(topic);
let value = JSON.stringify({'url': 'https://webhook.site/e40fa5de-239b-4dd6-a0dd-25e50f805d4e'})
client.set( key, value, function(err, result) {
if (err) throw err; // do something here...
result is 'OK'
});
The distribution of the notification message can be achieved by implementing the following pseudo code:
let client = redis.createClient();
mqtt_client.on('message', function (topic, message, packet) {
let key = md5(topic);
callbacks = client.get(key);
callbacks.foreach(callback) {
url = JSON.parse(callback).url;
request.post(
'http://www.yoursite.com/formpage',
{ json: message },
function (error, response, body) {
...
}
);
}
}
4.2.1.4. WebSub Extension Implementation (Webhook)
Any Webhook to be used with the W3C WebSub protocol must support the validation of subscription intent as defined in W3C WebSub — §5.3 Hub Verifies Intent of the Subscriber. Setting up a simple WebSub Webhook can be achieved quickly. How to setup a WebSub WebHook is illustrated below (after signing up for the basic plan).
The Webhook.site menu offers Custom Actions to configure the functionality using JavaScript. The following steps illustrate the setup for the demo Webhook used during the Code Sprint:
First, set global variables $hub.topic = https://citiobs.demo.secure-dimensions.de/staplustest/v1.1/Observations` and `$hub.secret = 'my great secret'.
Then, configure HTTP GET functionality via JavaScript
if ('GET' == get('request.method')) {
mode = get('request.query.hub_mode', null)
topic = get('request.query.hub_topic', null)
challenge = get('request.query.hub_challenge', null)
lease_seconds = get('request.query.hub_lease_seconds', null)
if (mode == null) {
respond('hub.mode required', 400, ['Content-Type: text/plain'])
return
}
if (topic == null) {
respond('hub.topic required', 400, ['Content-Type: text/plain'])
return
}
if (challenge == null) {
respond('hub.challenge required', 400, ['Content-Type: text/plain'])
return
}
console.log('topic: ' + topic)
console.log('hub.topic: ' + get('hub.topic'))
if (mode == 'unsubscribe') {
if (topic == get('hub.topic')) {
respond(challenge, 200, ['Content-Type: text/plain'])
return
} else {
respond('hub.topic unknown', 404, ['Content-Type: text/plain'])
return
}
}
if (mode == 'subscribe') {
if (lease_seconds == null) {
respond('hub.lease_seconds required', 400, ['Content-Type: text/plain'])
return
}
if (topic == get('hub.topic')) {
respond(challenge, 200, ['Content-Type: text/plain'])
return
} else {
respond('hub.topic unknown', 404, ['Content-Type: text/plain'])
return
}
}
}
To protect the Webhook from unauthorized execution, you can set an execution condition on the HTTP header X-API-Key:
$request.header.x-api-key$ 'is equal to' $hub.secret
And finally, to process the POSTed message from the Hub, the Webhook must validate the received HMAC to ensure that the source is the Hub. The following code implements this behavior:
crypto = require("crypto");
method = get('request.method')
secret = get('hub.secret')
if ('POST == method') {
x_hub_signature = get('request.header.x-hub-signature', null)
if (x_hub_signature == null) {
respond('HTTP header x-hub-signature is required', 400, ['Content-Type: text/plain'])
return
}
console.log("X-Hub-Signature: " + x_hub_signature)
signature = x_hub_signature.split('=');
if (signature.length != 2) {
console.log("X-Hub-Signature has wrong format: " + x_hub_signature);
console.log("Not sending message to client");
respond('', 204, ['Content-Type: text/plain'])
return
}
alg = signature[0];
console.log("signature algorithm: " + alg)
value = signature[1];
console.log("signature value: " + value)
data = get('request.content')
hmac = crypto.createHmac(alg, secret).update(data).digest("hex");
console.log("HMAC value computed from request: " + hmac)
if (hmac !== value) {
console.log("X-Hub-Signature validation failed. Not sending message to client");
respond('', 204, ['Content-Type: text/plain'])
return
}
console.log("processing data")
respond('', 204, ['Content-Type: text/plain'])
}
4.2.1.5. Code Sprint Contribution
The contribution to the code sprint focused on improving the Hub’s distribution of messages to callback URLs (Webhooks). The simple approach to send HTTP POST messages from inside the MQTT.on_message callback was modified such that the Hub now pushes the message to a processing queue. The queue was implemented using RabbitMQ. The use of a RabbitMQ Exchange is illustrated here. The use of a message queueing system improves the responsiveness of the Hub as the peculiarities of WebHooks (slow latency, offline, etc.) are now taken care of by the RabbitMQ queue consumer processes. To achieve scalability, it is possible to deploy multiple workers in the cloud. The Hub improvement during the code sprint boils down to the following code snippet:
const amqp = require("amqplib");
(async () => {
try {
var connection = await amqp.connect("amqp://localhost");
var channel = await connection.createChannel();
await channel.assertQueue("websub", {durable: false});
}
catch (err) {
console.warn(err);
}
})();
channel.sendToQueue("websub", Buffer.from(JSON.stringify(body)),
{
appId: callback,
contentType: 'application/json',
headers: headers,
correlationId: secret
});
On the message queue consumer side, the following code snippet illustrates the HTTP POSTing to the Webhooks:
const amqp = require("amqplib");
const request = require('request');
const crypto = require('crypto');
const log = require('loglevel');
log.setLevel(process.env.LOG_LEVEL || log.levels.DEBUG);
(async () => {
try {
const connection = await amqp.connect("amqp://localhost");
const channel = await connection.createChannel();
process.once("SIG---", async () => {
await channel.close();
await connection.close();
});
await channel.consume(
"websub",
(message) => {
if (message) {
let body = JSON.parse(message.content);
let headers = message.properties.headers;
let content_type = message.properties.contentType;
let secret = message.properties.correlationId;
let callback = message.properties.appId;
log.debug(" [x] Received '%s'", body);
log.debug(" [x] Headers '%s'", JSON.stringify(headers));
log.debug(" [x] Content-Type '%s'", content_type);
log.debug(" [x] secret '%s'", secret);
log.debug(" [x] callback '%s'", callback);
if (secret !== null) {
log.debug("message: " + body);
log.debug("secret: " + secret);
var hmac = crypto.createHmac("sha256", secret).update(body).digest("hex");
log.debug("hmac: " + hmac);
headers['X-Hub-Signature'] = 'sha256=' + hmac;
}
request.post({
headers: headers,
url: callback,
body: body
}, function (error, response, body) {
log.info("message sent with HMAC: " + hmac);
if (error) {
log.debug(error);
}
});
}
},
{ noAck: true }
);
console.log(" [*] Waiting for messages. To exit press CTRL+C");
} catch (err) {
console.warn(err);
}
})();
For achieving scalability, it is required that a queue worker is stateless. As illustrated above, this is achieved by adding all relevant information to the message itself. In the example above, the AMQP message property message.properties.appId refers to the Webhook URL, message.properties.correlationId refers to the HMAC secret. The ‘mis’use of these properties like this or in a similar fashion is required as the RabbitMQ implementation does not seem to support a generic message property like ‘userdata’ or ‘options’. When conveying more information, it is also possible to JSON.stringify({…}) all relevant information into one of the message properties. This does not create an interoperability challenge as it is likely that the Hub and the Worker is implemented by the same entity. And therefore, the ‘mis’use of RabbitMQ message properties for a specific purpose can easily be done.
Beside the fault tolerant distribution of messages to Webhooks, the calculation of the HMAC for each message is now computed at the Worker. This also improves the deployment responsiveness, as different queues for different message size can be deployed to hosting environments with fit-for-purpose CPU and memory requirements. This ensures an optimized throughput even for large messages that require HMAC calculation.
Future work will focus on the proper use of a RabbitMQ Exchange leveraging the use of multiple message queues connected to distributed worker systems. Even though the implementation based on RabbitMQ is simple, the routing policy for the exchange needs to consider the characteristics of the receiving Webhook, the message size, HMAC calculation requirements, etc.
4.2.2. OGC API — Records
Experimentation related to OGC API — Records included extension of pygeoapi to enable support for TrainingDataML-AI. A detailed summary is presented in Clause 4.4.1. The prototype potentially could lead to a TrainingDataML-AI profile of the Record Core model specified in OGC API — Records — Part 1: Core. The pygeoapi implementation mapped the common metadata constructs into the Record Core model, and encoded TrainingDataML-AI specifics accordingly.
4.2.3. OGC Styles and Symbology
During this code sprint, the sprint participants worked on drafting the OGC Styles & Symbology candidate standard. The work included:
discussing possible use cases for hatch, stipple & pattern fills,
addition of a Metadata section in the Requirements Class “Core” with keywords and geoDataClasses parameters in line with the JSON schema,
discussion and clarification of the concepts of Stipples and Hatches,
drafting requirements with portrayal examples,
creating placeholders for the Abstract Test Suite,
discussion and clarification of viz.pass, feature.pass and zOrder concepts,
a discussion also took place on consistency of UML class diagrams (see #74),
work on a future CartoSym transcoder,
discussion with Tom Kralidis on the possibility of implementing OGC API — Styles in pygeoapi based on the GetStyles operation of a WMS service,
discussion with Gobe Hobona on the relevance of using Enterprise Architect for UML modelling,
work on updating the SWG charter, clarifying the work items for Cartographic Symbology 2.0 parts 1-4, and proposing to rename the SWG to “Cartographic Symbology” to align with the name of the standard as well as the “CartoSym” encodings, and avoiding confusion with the scope of the OGC API — Styles SWG.
A number of GitHub issues were created as a result of this work. This included:
#24: Custom fill
#57: Add keywords element in Style node
#59: Rename hatchstyle to hatch and new properties
#62: Move Metadata in 1-core
#63: Complete full list of requirements for 1-core
#64: Rename stippleStyle to stipple
#71: Add support to allow arbitrary Expressions (not only literals) for all Symbolizer properties
#74: UML class diagrams
#76: Clarify viz.pass, feature.pass and zOrder concepts
4.2.3.1. Styles and Symbology Conclusions
The code sprint enabled the editors of the OGC Cartographic Symbology candidate standard to work together on drafting the standard. They were able to clarify some concepts, requirements and use cases and moved the standard forward. A number of important tasks remain to be completed before CartoSym 2.0 — Part 1 can be finalized.
These tasks include:
detailing the requirements, including examples of rendering with the corresponding CartoSym-CSS encoding examples in the Requirements Classes and appendix B: Mapping of SLD/SE and notable vendor extensions to the Conceptual Model
update the UML class diagrams (see #74),
writing the Annex A: “Abstract Test Suite (Normative)” as already started here,
implementing transcoders and rendering engines,
define a global UML class hierarchy diagram covering all of the Requirements Classes. Enterprise Architect could be a useful tool for this. It would also enable the SWG to generate an XSD schema and a JSON schema so that we can check the consistency of the existing schema. The UML to JSON conversion tool imvertor-lite could also be considered,
check that the JSON schema complies with the candidate Best Practice for OGC — UML to JSON Encoding Rules.
4.3. Specifications from the Community
4.3.1. MapML
Several participants worked on this MapML track.
4.3.1.1. pygeoapi
Pygeoapi was used as the base for a prototype web application that is able to serve MapML remote content.
The original goal was to add MapML support by leveraging pygeoapi’s plugin framework. However, after inspection of the code this proved to not be possible — proper integration of MapML would require modifications to the core pygeoapi code, something which was deemed out of scope for the code sprint. As such, development efforts consisted of developing a thin wrapper around pygeoapi which would add the relevant bits of MapML-related code while still keeping pygeoapi as the main agent. This approach worked out well.
The prototype thus consisted of two-components:
A pygeoapi plugin that defined a tile-based data provider which knew how to respond to requests with the Accept:text/mapml header
A small middleware for pygeoapi’s Flask application which intercepted relevant requests and performed post-processing of the pygeoapi response in order to add support for MapML
In order to test the results, a simple web-based client was also implemented as a separate application. This web client featured the <mapml-viewer> element and configured remote layers that were being fetched from our prototype.
4.3.1.1.1. pygeoapi MapML tile provider plugin
Taking advantage of pygeoapi’s extensibility the existing tile provider was subclassed in order to add support for responding with a MapML document to requests for tileset metadata. In the context of the code sprint, support was restricted to the WebMercatorQuad tileset. A sample request would be:
GET /collections/{collection-id}/tiles/WebMercatorQuad "Accept:text/mapml"Listing 1 — Request
The custom tile provider was implemented as to recognize the MapML media type being requested in the request’s Accept header and to generate a suitable MapML document as the response. This allowed the pygeoapi-based prototype to serve as a server for OGC API Tiles, which generic clients would be able to use for requesting MapML data. The server thus generated a response like:
<mapml- xmlns="http://www.w3.org/1999/xhtml">
<map-head>
<map-title>Prevalence rates of mental health issues in London</map-title>
<map-meta http-equiv="Content-Type" content="text/mapml;projection=OSMTILE"></map-meta>
<map-meta charset="utf-8"></map-meta>
<map-meta name="extent" content="top-left-easting=-29028.26648413821, top-left-northing=6694074.574114459, bottom-right-easting=14106.427797324195, bottom-right-northing=6724542.93687513"></map-meta>
<map-link rel="license" href="" title=""></map-link>
</map-head>
<map-body>
<map-extent units="OSMTILE" checked="checked">
<map-input name="tileMatrix" type="zoom" value="0" min="0" max="18"></map-input>
<map-input name="tileCol" type="location" units="tilematrix" axis="column"></map-input>
<map-input name="tileRow" type="location" units="tilematrix" axis="row"></map-input>
<map-link rel="tile" tref="http://localhost:5000/collections/grid_mental/tiles/WebMercatorQuad/{tileMatrix}/{tileRow}/{tileCol}?f=png"></map-link>
</map-extent>
</map-body>
</mapml->
Listing 2 — pygeoapi-based prototype response to tile metadata request
4.3.1.1.2. pygeoapi wrapper code
The pygeoapi wrapper code, which was implemented as a Flask after_request() callback, dealt with adding support for the text/mapml media type for some endpoints and mostly with converting features encoded in GeoJSON to their respective MapML representations, thus making it possible to have support for remote MapML features.
http /collections/{collection-id}/items "Accept:text/mapml" limit==1Listing 3 — Example request for features using the mapml media-type
With the prototype pygeoapi-based application generating the following response:
<mapml- xmlns="http://www.w3.org/1999/xhtml">
<map-head>
<map-title>Observations</map-title>
<map-meta name="projection" content="OSMTILE"></map-meta>
<map-meta http-equiv="Content-Type" content="text/mapml;projection=OSMTILE"></map-meta>
<map-meta charset="utf-8"></map-meta>
<map-meta name="cs" content="gcrs"></map-meta>
<map-meta name="extent" content="top-left-longitude=-122, top-left-latitude=49, bottom-right-longitude=-75, bottom-right-latitude=43"></map-meta>
<map-link rel="license" href="" title=""></map-link>
</map-head>
<map-body><map-feature>
<map-properties>
<table>
<tbody><tr>
<td>stn_id</td>
<td>35</td>
</tr><tr>
<td>datetime</td>
<td>2001-10-30T14:24:55Z</td>
</tr><tr>
<td>value</td>
<td>89.9</td>
</tr></tbody>
</table>
</map-properties>
<map-geometry><map-point><map-coordinates>-75.00000000 45.00000000</map-coordinates></map-point></map-geometry>
</map-feature></map-body>
</mapml->
Listing 4 — Response
4.3.1.1.3. Simple MapML web client
In order to test how the pygeoapi-based prototype worked as a server of remote MapML data, a small web client was implemented, making use of the @maps4html/web-map-custom-element javascript library, which emulates support for MapML in the browser.
The client asked for a couple of remote layers, being served by the pygeoapi-based prototype application. One of these remote layers served image tiles, while the other served MapML features.
<mapml-viewer projection="OSMTILE" zoom="1" lat="0.0" lon="0.0" controls>
<layer- label="OpenStreetMap" checked>
<map-extent units="OSMTILE" checked>
<map-input name="z" type="zoom" value="18" min="0" max="18"></map-input>
<map-input name="x" type="location" units="tilematrix" axis="column" min="0" max="262144" ></map-input>
<map-input name="y" type="location" units="tilematrix" axis="row" min="0" max="262144" ></map-input>
<map-link rel="tile" tref="https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" ></map-link>
</map-extent>
</layer->
<layer-
label="grid mental from pygeoapi"
src="https://da08-167-98-97-210.ngrok-free.app/collections/grid_mental/tiles/WebMercatorQuad"
checked
></layer->
<layer-
label="obs from pygeoapi"
src="https://da08-167-98-97-210.ngrok-free.app/collections/obs/items"
checked
></layer->
</mapml-viewer>
Listing 5 — Simple web based client for testing the MapML remote content being served by the pygeoapi-based prototype
Below is a sample image demonstrating the operation of this simple web client.
Figure 12 — Simple web client displaying a layer fetched from the remote pygeoapi-based prototype.
4.3.1.2. CREAF Miramon
UAB-CREAF participated in the sprint by contributing their MiraMon Map Server. This application was adapted to OGC API Maps and Tiles during previous sprints. The OGC API Maps allow for requesting a map of a collection. If the request is done to this endpoint /collections/{collectionId}/map with no parameters, the server is free to respond with a “nice” map that represents the collection or a representative area of it. If the negotiated media type is static, the selection of the area is particularly important. In the case of MapML, the map is interactive, giving freedom to the user to correct the server decision by panning and zooming. In this particular sprint, two modifications were introduced in the MiraMon Map Server to include MapML support.
A request to a /collections/{collectionId}/map with no extra parameters that negotiates HTML and results in the creation of an HTML page that includes some metadata about the collection and a MapML section to show the interactive map. This web page can be visualized in the map browser with the help of MapML common JavaScript libraries.
A request to a /collections/{collectionId}/map with no extra parameters that negotiates MapML, and results in a MapML document that can be visualized in Chrome if an specific add-in has been previously setup.
Figure 13 — Contiguous tiles from different services and APIs sharing same WebMercatorQuad tile matrix set and the tile matrix identified as 15 (sometimes called "zoom")
Figure 14 — Contiguous tiles from different services and APIs sharing same WebMercatorQuad tile matrix set and the tile matrix identified as 15 (sometimes called "zoom")
In both cases the MiraMon Map Server implementing OGC API — Maps is used twice:
It produces the initial response to the “minimalistic” map request (with no parameters) asking for the HTML or MapML representation of the collection.
The MapML content uses the URL template mechanism to get an image map (in this case a PNG) of the current view and the subsequent views that the user will generate by panning and zooming into the map.
The following code is common to both MapML responses (HTML or MapML versions). Please note that the OGC API — Maps is used to generate the PNGs maps. The HTML element map-link contains a link to a URL template that once “resolved” with the right map-input values become a call that conforms to the OGC API maps. This demonstrates that the current specification of MapML can use the new OGC API Maps with no modification.
<map-extent units="WGS84" label="etopo2" checked="checked">
<map-input name="z" type="zoom" min="1" max="15"></map-input>
<map-input name="w" type="width"></map-input>
<map-input name="h" type="height"></map-input>
<map-input name="xmin" type="location" units="pcrs" position="top-left" axis="easting" ></map-input>
<map-input name="ymin" type="location" units="pcrs" position="bottom-left" axis="northing" ></map-input>
<map-input name="xmax" type="location" units="pcrs" position="top-right" axis="easting" ></map-input>
<map-input name="ymax" type="location" units="pcrs" position="top-left" axis="northing" ></map-input>
<map-link rel="image" tref="https://www.ogc3.grumets.cat/cgi-bin/world/miramon.cgi/collections/etopo2/map?crs=http://www.opengis.net/def/crs/OGC/1.3/CRS84&bbox-crs=http://www.opengis.net/def/crs/OGC/1.3/CRS84&bbox={xmin},{ymin},{xmax},{ymax}&width={w}&height={h}&f=PNG&transparent=true"></map-link>
</map-extent>
Listing 6
In case the API implementation supports MapML, it is convenient that the collection description page advertises a link to the map. The following figure illustrates how this looks like in the HTML representation of the response.
Figure 15 — Contiguous tiles from different services and APIs sharing same WebMercatorQuad tile matrix set and the tile matrix identified as 15 (sometimes called "zoom")
4.3.1.3. GNOSIS Map Server
The official MapML client was tested with outputs from OGC API endpoints of the GNOSIS Map Server for multiple access mechanisms: OGC API — Maps, OGC API — Features and OGC API — Tiles (for both map tiles and vector tiles).
An HTML page was set up to demonstrate these capabilities, where the user can toggle the visibility of a map, map tiles, vector features and vector tiles.
For the features and vector tiles experiments, the client accessed a MapML representation of the vector tiles and features, including their geometry, which was previously implemented in the GNOSIS Map Server for OGC Testbed 15.
Figure 16 — Maps and features being accessed from the GNOSIS Map Server implementation of OGC API - Maps and OGC API - Features in the MapML client
Figure 17 — Vector tiles and map tiles being accessed from the GNOSIS Map Server implementation of OGC API - Tiles in the MapML client
Some rendering issues were noticed in the client with the vector features and vector tiles, with the vector tiles issues more significant. This is possibly caused by invalid geometry generated by the server, issues on the client side, or a combination of both. These issues should be investigated further and addressed.
Figure 18 — Visual artifacts visualizing vector tiles from the GNOSIS Map Server implementation of OGC API - Tiles in the MapML client
Figure 19 — Visual artifacts visualizing features from the GNOSIS Map Server implementation of OGC API - Features in the MapML client
A future version of the GNOSIS Map Server could support a MapML representation of the /map endpoint which automatically set up the MapML elements for the different layers available at that end-point. This representation would need to choose between the different possible access mechanisms, or offer all of them while only making one visible by default, allowing the user to access the same data in different ways.
4.3.1.4. Experimentation by Rui Cavaco
Rui Cavaco‘s work (in person at code sprint) had three different ‘tracks’:
get a more complete understanding of the MapML concept, experimenting with reference implementation polyfill examples;
experimenting with JavaScript, possibly extending some polyfill’s functionality;
understand polyfill support to projected CRS’s such as ‘national grids’.
At first, it was clear that MapML itself, and the reference implementation polyfill, show several capabilities which manifest themselves when one goes beyond the simplest OSM tiling examples.
Three examples of this:
the map-extent element (and the possibility of there existing several for each layer);
the combining of the “projection” attribute and of “units” attribute;
the OSMTILES, CBTILES and other keywords for “projection” or “units”.
The necessity to go through several examples to fully grasp the MapML capability became very clear.
Also became quite clear that it is not crucial to extend polyfill’s functionality, since it is supposed that such functionality should be, sooner or later, transferred to browser’s code bases.
So Rui Cavaco’s final work in the code sprint was focused on JavaScript DOM manipulation using, one of MapML’s most interesting features: the ability to, easily, add dynamic changes to web maps. In this case, a real world problem was addressed, the ability to add to and remove from, a web map, at user’s request, some municipal-scale themes from Northern Portugal region.
To this purpose a webapp was built using MapML polyfill from Maps4HTML and Holoviz Panel Python web framework.
Slides describing this work in more detail can be found here. The code repository on GitHub you can find it here.
4.3.2. ISO 19157-3 Data Quality Measures Register
A current version of the ISO 19157-3 register that is available through OGC RAINBOW contains an initial set of more than 80 recognized standard data quality measures (e.g. such as the Root Mean Square Error used for evaluation positional accuracy, or the Misclassification Matrix used to evaluate the attribute accuracy). A screenshot of the register is shown in Figure 20. The data quality measures were used in the first few tests as part of the Code Sprint.
Figure 20 — A screenshot of the data quality measures register display on OGC RAINBOW
As one of the major focuses of the code sprint was the use, testing, and enhancement of data quality documentation in AI applications, the JSON encoding of the Training Data Markup Language for AI (TrainingDML-AI) Standard was used as the target for testing the potential use of the ISO 19157-3 data quality measures register in the context of AI. The example dataset is a simple, reduced and modified version of the dataset link. This is shown below:
{
"type": "DataQuality",
"scope": {
"level": "dataset",
"levelDescription": [
{
"dataset": "main.bld_fts_building"
}
]
},
"report": [
{
"type": "PositionalAccuracy",
"measure": {
"measureIdentification": {
"code": "FT28_2",
"authority": "https://defs-dev.opengis.net/vocprez-hosted/object?uri=https%3A//standards.isotc211.org/19157/-3/1/dqc/content/formulaType/"
},
"nameOfMeasure": [
"Absolute Value of mean error to the standard deviation",
"Horizontal"
],
"measureDescription": "Calculates the mean error of the standard deviation"
},
"evaluationMethod": {
"evaluationMethodDescription": "Uses the standard mathematical formula"
},
"result": [
{
"quantitativeResult": {
"value": [
0.75643
],
"valueUnit": "real"
}
}
]
}
]
}
Listing 7
The test dataset contains the PositionalAccuracy element which implements the measureIdentification element that in turn includes the reference to the authority and a code that corresponds to the data quality formula expressed in MathML. The measureIdentification element in the listing above references a data quality measure that is defined through a mathematical formula. The URI reference leads to a page as shown in Figure 21 when displayed in a web browser.
Figure 21 — A screenshot of a mathematical formular from the data quality measures register
One of the objectives of the software developed in this part of the code sprint was to parse the MathML to make it machine readable, machine executable, and parsable. The output was successful to a point of making the formula machine readable, but it was not possible to inject new variables into the formula to execute the chain for another dataset.
4.4. Software Projects and Products
4.4.1. OSGeo pygeoapi
4.4.1.1. Mentor stream: Adding a new OGC API to pygeoapi
Given recent updates to pygeoapi in support of API implementation modularity, a mentor stream was given, focusing on adding a new OGC API to pygeoapi. Developers were shown how to add and hook new API functionality / endpoints into the pygeoapi core, as well as exposing via pygeoapi’s OpenAPI functionality. A presentation and example application were demonstrated and made available as proof of concept.
Figure 22
4.4.1.1.1. OGC API — Processes — Part 2 implementation
An initial prototype was implemented to support the OGC API — Processes — Part 2: Deploy, Replace, Undeploy draft standard. Process creation was implemented by way of ingesting a Common Workflow Language (CWL) definition which referenced a Python application made available as a Docker image. The Python application implemented water body detection, which took as input Copernicus Sentinel-2 or USSG Landsat-9 data and detected water bodies by applying the Otsu thresholding technique on the Normalized Difference Water Index (NDWI)1. This application was made available as an example in support of the OGC Best Practice for Earth Observation Application Package.
Figure 23
The CWL was published and made available as an OGC API Process. The process description included an executionUnit object providing the CWL definition.
Process execution then invoked the cwltool reference implementation to deploy and run the application in a portable manner, producing a manifest of a STAC Catalog of the NDWI outputs.
Figure 24
The architecture of the implementation can be found below, and the associated implementation on GitHub. Future work includes ‘process replace’ and ‘process delete’ functionality, as well as describing CWL inputs and outputs as part of the native process description model.
Figure 25
Special thanks is given to the Earth Observation Application Package resources and examples provided on GitHub as well as Gérald Fenoy of GeoLabs SARL for providing valuable explanation, advice and recommendation.
4.4.2. OSGeo pygeometa
Upon participating in the special track and breakout session focused on Data Quality and Artificial Intelligence, an initial Training Data Markup Language for AI (TrainingDML-AI) encoder was implemented in pygeometa. This enabled configuring a training dataset as a pygeometa metadata control file (MCF) configuration and generating TrainingDataML-AI (or any other metadata format supported by pygeometa). Note that the MCF model was extended to support specifics of TrainingDataML-AI.
The initial exercise illustrated a number of intersections between TrainingDataML-AI and common metadata constructs (spatiotemporal extents, keywords, contacts, data quality, etc.) in support of discovery and documentation. As a result, an additional implementation was put forth to create a TrainingDataML-AI profile of the OGC API — Records — Part 1: Core, Record Core model. This implementation mapped the common metadata constructs into the Record Core model, and encoded TrainingDataML-AI specifics accordingly.
The result of this experiment was the encoding of a training dataset description as a metadata record that could then enable low barrier, broad interoperability via GeoJSON and OGC API — Records.
Figure 26
The resulting implementation can be found on GitHub.
4.4.3. CubeWerx Geospatial Data Server
4.4.3.1. Overview
CubeWerx’s involvement in the code sprint consisted of updating their features server to be compliant with the latest draft versions of the candidate Standards:
CubeWerx’s features server is part of the CubeWerx Geospatial Data Server (“cubeserv”) which is implemented in C and currently implements the following OGC Standards and draft specifications.
Multiple conformance classes and recommendations of the OGC API — Tiles — Part 1: Core Standard
Multiple conformance classes and recommendations of the OGC API — Maps — Part 1: Core candidate Standard
All conformance classes and recommendations of the OGC API — Features — Part 1: Core Standard
Multiple conformance classes and recommendations of the OGC API — Records — Part 1: Core candidate Standard
Multiple conformance classes and recommendations of the OGC API — Coverages — Part 1: Core candidate Standard
Multiple conformance classes and recommendations of the OGC API — Processes — Part 1: Core Standard
Multiple versions of the Web Map Service (WMS), Web Processing Service (WPS), Web Map Tile Service (WMTS), and Web Feature Service (WFS) Standards
A number of other “un-adopted” OGC Web Service draft specifications including the Testbed-12 Web Integration Service, OWS-7 Engineering Report — GeoSynchronization Service, and the Web Object Service prototype.
The cubeserv executable supports a wide variety of back ends including Oracle, MariaDB, SHAPE files, etc. It also supports a wide array of service-dependent output formats, for example, Geography Markup Language (GML), GeoJSON, Mapbox Vector Tiles, MapMP, as well as several coordinate reference systems.
4.4.3.2. Schemas
4.4.3.2.1. Overview
Cubeserv implements the following endpoints for retrieving a schema:
/collections/{collectionId}/schema
/collections/{collectionId}/queryables
/collections/{collectionId}/sortable
These endpoints are as defined in OGC API — Features — Part 5: Schemas. These endpoints, however, only provide “logical” schemas and cannot, thus, be used for validation. In order to support validation, cubeserv also provides the following endpoints for retrieving application schemas:
/collections/{collectionId}/schemas/collection
/collections/{collectionId}/schemas/feature
The first endpoint provides an application schema that allows a response containing a collection of features to be validated. The latter endpoint provides an application schema that can be used to validate a single feature.
Cubeserv implements the following conformance classes from OGC API — Features — Part 5: Schemas:
Table 1 — Conformance class URIs
| Conformance class | URI |
|---|---|
| Schemas | http://www.opengis.net/spec/{standard}/{m_n}/conf/schemas |
| Core roles for features | http://www.opengis.net/spec/{standard}/{m_n}/conf/core-roles-features |
| Returnables and Receivables | http://www.opengis.net/spec/{standard}/{m_n}/conf/returnables-and-receivables |
| Queryables | http://www.opengis.net/spec/{standard}/{m_n}/conf/queryables |
| Sortables | http://www.opengis.net/spec/{standard}/{m_n}/conf/sortables |
4.4.3.2.2. Examples
Example 1 — Logical schema response
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/SettlementSrf/schema",
"type": "object",
"title": "No Title Specified",
"description": "No description provided.",
"properties": {
"cw_fid": {
"readOnly": true,
"x-ogc-role": "id",
"type": "string",
"format": "uuid",
"x-ogc-propertySeq": 1
},
"geometry": {
"format": "geometry-polygon",
"x-ogc-role": "primary-geometry",
"x-ogc-propertySeq": 2
},
"AOO": {
"type": "number",
"x-ogc-propertySeq": 3
},
"ARA": {
"type": "number",
"x-ogc-propertySeq": 4
},
"BAC": {
"type": "integer",
"x-ogc-propertySeq": 5
},
"BEN": {
"type": "string",
"x-ogc-propertySeq": 6
},
"CAA": {
"type": "integer",
"x-ogc-propertySeq": 7
},
"CCN": {
"type": "string",
"x-ogc-propertySeq": 8
},
"CDR": {
"type": "string",
"x-ogc-propertySeq": 9
},
"FFN": {
"type": "integer",
"x-ogc-propertySeq": 10
},
"FFN2": {
"type": "integer",
"x-ogc-propertySeq": 11
},
"FFN3": {
"type": "integer",
"x-ogc-propertySeq": 12
},
"F_CODE": {
"type": "string",
"x-ogc-propertySeq": 13
},
"HGT": {
"type": "number",
"x-ogc-propertySeq": 14
},
"LZN": {
"type": "number",
"x-ogc-propertySeq": 15
},
"OTH": {
"type": "string",
"x-ogc-propertySeq": 16
},
"PCF": {
"type": "integer",
"x-ogc-propertySeq": 17
},
"SAX_RS1": {
"type": "string",
"x-ogc-propertySeq": 18
},
"SAX_RS2": {
"type": "string",
"x-ogc-propertySeq": 19
},
"SAX_RS3": {
"type": "string",
"x-ogc-propertySeq": 20
},
"SAX_RS4": {
"type": "string",
"x-ogc-propertySeq": 21
},
"SAX_RS5": {
"type": "string",
"x-ogc-propertySeq": 22
},
"SAX_RS6": {
"type": "string",
"x-ogc-propertySeq": 23
},
"SAX_RS8": {
"type": "string",
"x-ogc-propertySeq": 24
},
"SAX_RS9": {
"type": "string",
"x-ogc-propertySeq": 25
},
"SAX_RX1": {
"type": "string",
"x-ogc-propertySeq": 26
},
"SAX_RX2": {
"type": "string",
"x-ogc-propertySeq": 27
},
"SAX_RX5": {
"type": "string",
"x-ogc-propertySeq": 28
},
"SAX_RX6": {
"type": "string",
"x-ogc-propertySeq": 29
},
"SAX_RX7": {
"type": "string",
"x-ogc-propertySeq": 30
},
"SAX_RX8": {
"type": "string",
"x-ogc-propertySeq": 31
},
"SAX_RX9": {
"type": "string",
"x-ogc-propertySeq": 32
},
"SAX_RY0": {
"type": "string",
"x-ogc-propertySeq": 33
},
"SAX_RY1": {
"type": "string",
"x-ogc-propertySeq": 34
},
"SAX_RY2": {
"type": "string",
"x-ogc-propertySeq": 35
},
"UFI": {
"type": "string",
"x-ogc-propertySeq": 36
},
"WID": {
"type": "number",
"x-ogc-propertySeq": 37
},
"WPI": {
"type": "string",
"x-ogc-propertySeq": 38
},
"ZI001_SDP": {
"type": "string",
"x-ogc-propertySeq": 39
},
"ZI001_SDV": {
"type": "string",
"x-ogc-propertySeq": 40
},
"ZI001_SPS": {
"type": "integer",
"x-ogc-propertySeq": 41
},
"ZI001_SRT": {
"type": "string",
"x-ogc-propertySeq": 42
},
"ZI001_VSC": {
"type": "string",
"x-ogc-propertySeq": 43
},
"ZI001_VSD": {
"type": "string",
"x-ogc-propertySeq": 44
},
"ZI001_VSN": {
"type": "string",
"x-ogc-propertySeq": 45
},
"ZI004_RCG": {
"type": "string",
"x-ogc-propertySeq": 46
},
"ZI005_FNA": {
"type": "string",
"x-ogc-propertySeq": 47
},
"ZI005_FNA2": {
"type": "string",
"x-ogc-propertySeq": 48
},
"ZI005_NFN": {
"type": "string",
"x-ogc-propertySeq": 49
},
"ZI005_NFN2": {
"type": "string",
"x-ogc-propertySeq": 50
},
"ZI006_MEM": {
"type": "string",
"x-ogc-propertySeq": 51
},
"ZI020_GE4": {
"type": "string",
"x-ogc-propertySeq": 52
},
"ZI026_CTUC": {
"type": "integer",
"x-ogc-propertySeq": 53
},
"ZI026_CTUL": {
"type": "integer",
"x-ogc-propertySeq": 54
},
"ZI026_CTUU": {
"type": "integer",
"x-ogc-propertySeq": 55
},
"ZSAX_RS0": {
"type": "string",
"x-ogc-propertySeq": 56
},
"ZSAX_RX0": {
"type": "string",
"x-ogc-propertySeq": 57
},
"ZSAX_RX3": {
"type": "string",
"x-ogc-propertySeq": 58
},
"ZSAX_RX4": {
"type": "string",
"x-ogc-propertySeq": 59
},
"ZVH": {
"type": "number",
"x-ogc-propertySeq": 60
},
"FCSUBTYPE": {
"type": "integer",
"x-ogc-propertySeq": 61
},
"ADR": {
"type": "string",
"x-ogc-propertySeq": 62
},
"LMC": {
"type": "integer",
"x-ogc-propertySeq": 63
},
"STL": {
"type": "integer",
"x-ogc-propertySeq": 64
},
"STL2": {
"type": "integer",
"x-ogc-propertySeq": 65
},
"STL3": {
"type": "integer",
"x-ogc-propertySeq": 66
},
"HHD": {
"type": "integer",
"x-ogc-propertySeq": 67
}
},
"additionalProperties": false
}
Example 2 — Application schema for the collection
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/schemas/collection",
"$defs": {
"bbox": {
"type": "array",
"minItems": 4,
"items": {
"type": "number"
}
},
"link": {
"type": "object",
"required": [
"href"
],
"properties": {
"href": {
"type": "string",
"format": "uri"
},
"rel": {
"type": "string"
},
"type": {
"type": "string"
},
"title": {
"type": "string"
}
}
},
"Point": {
"title": "GeoJSON Point",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Point"
]
},
"coordinates": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"LineString": {
"title": "GeoJSON LineString",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"LineString"
]
},
"coordinates": {
"type": "array",
"minItems": 2,
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"Polygon": {
"title": "GeoJSON Polygon",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Polygon"
]
},
"coordinates": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"MultiPoint": {
"title": "GeoJSON MultiPoint",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiPoint"
]
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"MultiLineString": {
"title": "GeoJSON MultiLineString",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiLineString"
]
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"MultiPolygon": {
"title": "GeoJSON MultiPolygon",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiPolygon"
]
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
}
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"GeometryCollection": {
"title": "GeoJSON Geometry Collection",
"type": "object",
"required": [
"type",
"geometries"
],
"properties": {
"type": {
"type": "string",
"enum": [
"GeometryCollection"
]
},
"geometries": {
"type": "array",
"items": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/$defs/Point"
},
{
"$ref": "#/$defs/MultiPoint"
},
{
"$ref": "#/$defs/LineString"
},
{
"$ref": "#/$defs/MultiLineString"
},
{
"$ref": "#/$defs/Polygon"
},
{
"$ref": "#/$defs/MultiPolygon"
}
]
}
},
"bbox": {
"$ref": "#/$defs/bbox"
}
}
},
"SettlementSrf": {
"featureType": "SettlementSrf",
"type": "object",
"required": [
"type",
"geometry",
"properties"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Feature"
]
},
"id": {
"type": "string"
},
"bbox": {
"$ref": "#/$defs/bbox"
},
"geometry": {
"$ref": "#/$defs/Polygon"
},
"properties": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"required": [
],
"properties": {
"AOO": {
"type": "number"
},
"ARA": {
"type": "number"
},
"BAC": {
"type": "integer"
},
"BEN": {
"type": "string"
},
"CAA": {
"type": "integer"
},
"CCN": {
"type": "string"
},
"CDR": {
"type": "string"
},
"FFN": {
"type": "integer"
},
"FFN2": {
"type": "integer"
},
"FFN3": {
"type": "integer"
},
"F_CODE": {
"type": "string"
},
"HGT": {
"type": "number"
},
"LZN": {
"type": "number"
},
"OTH": {
"type": "string"
},
"PCF": {
"type": "integer"
},
"SAX_RS1": {
"type": "string"
},
"SAX_RS2": {
"type": "string"
},
"SAX_RS3": {
"type": "string"
},
"SAX_RS4": {
"type": "string"
},
"SAX_RS5": {
"type": "string"
},
"SAX_RS6": {
"type": "string"
},
"SAX_RS8": {
"type": "string"
},
"SAX_RS9": {
"type": "string"
},
"SAX_RX1": {
"type": "string"
},
"SAX_RX2": {
"type": "string"
},
"SAX_RX5": {
"type": "string"
},
"SAX_RX6": {
"type": "string"
},
"SAX_RX7": {
"type": "string"
},
"SAX_RX8": {
"type": "string"
},
"SAX_RX9": {
"type": "string"
},
"SAX_RY0": {
"type": "string"
},
"SAX_RY1": {
"type": "string"
},
"SAX_RY2": {
"type": "string"
},
"UFI": {
"type": "string"
},
"WID": {
"type": "number"
},
"WPI": {
"type": "string"
},
"ZI001_SDP": {
"type": "string"
},
"ZI001_SDV": {
"type": "string"
},
"ZI001_SPS": {
"type": "integer"
},
"ZI001_SRT": {
"type": "string"
},
"ZI001_VSC": {
"type": "string"
},
"ZI001_VSD": {
"type": "string"
},
"ZI001_VSN": {
"type": "string"
},
"ZI004_RCG": {
"type": "string"
},
"ZI005_FNA": {
"type": "string"
},
"ZI005_FNA2": {
"type": "string"
},
"ZI005_NFN": {
"type": "string"
},
"ZI005_NFN2": {
"type": "string"
},
"ZI006_MEM": {
"type": "string"
},
"ZI020_GE4": {
"type": "string"
},
"ZI026_CTUC": {
"type": "integer"
},
"ZI026_CTUL": {
"type": "integer"
},
"ZI026_CTUU": {
"type": "integer"
},
"ZSAX_RS0": {
"type": "string"
},
"ZSAX_RX0": {
"type": "string"
},
"ZSAX_RX3": {
"type": "string"
},
"ZSAX_RX4": {
"type": "string"
},
"ZVH": {
"type": "number"
},
"FCSUBTYPE": {
"type": "integer"
},
"ADR": {
"type": "string"
},
"LMC": {
"type": "integer"
},
"STL": {
"type": "integer"
},
"STL2": {
"type": "integer"
},
"STL3": {
"type": "integer"
},
"HHD": {
"type": "integer"
}
},
"additionalProperties": false
}
]
},
"links": {
"type": "array",
"items": {
"type": "object",
"required": [
"href"
],
"properties": {
"href": {
"type": "string",
"format": "uri"
},
"rel": {
"type": "string"
},
"type": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
}
},
"title": "GeoJSON Feat Collection",
"type": "object",
"required": [
"type",
"features"
],
"properties": {
"type": {
"type": "string",
"enum": [
"FeatureCollection"
]
},
"features": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/$defs/SettlementSrf"
}
]
}
},
"bbox": {
"type": "array",
"minItems": 4,
"items": {
"type": "number"
}
}
}
}
Example 3 — Application schema for a feature
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/SettlementSrf/schema",
"type": "object",
"required": [
"type",
"geometry",
"properties"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Feature"
]
},
"id": {
"type": "string"
},
"bbox": {
"type": "array",
"minItems": 4,
"items": {
"type": "number"
}
},
"geometry": {
"title": "GeoJSON Polygon",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Polygon"
]
},
"coordinates": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "number"
}
}
},
"bbox": {
"type": "array",
"minItems": 4,
"items": {
"type": "number"
}
}
}
},
"properties": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"required": [
],
"properties": {
"AOO": {
"type": "number"
},
"ARA": {
"type": "number"
},
"BAC": {
"type": "integer"
},
"BEN": {
"type": "string"
},
"CAA": {
"type": "integer"
},
"CCN": {
"type": "string"
},
"CDR": {
"type": "string"
},
"FFN": {
"type": "integer"
},
"FFN2": {
"type": "integer"
},
"FFN3": {
"type": "integer"
},
"F_CODE": {
"type": "string"
},
"HGT": {
"type": "number"
},
"LZN": {
"type": "number"
},
"OTH": {
"type": "string"
},
"PCF": {
"type": "integer"
},
"SAX_RS1": {
"type": "string"
},
"SAX_RS2": {
"type": "string"
},
"SAX_RS3": {
"type": "string"
},
"SAX_RS4": {
"type": "string"
},
"SAX_RS5": {
"type": "string"
},
"SAX_RS6": {
"type": "string"
},
"SAX_RS8": {
"type": "string"
},
"SAX_RS9": {
"type": "string"
},
"SAX_RX1": {
"type": "string"
},
"SAX_RX2": {
"type": "string"
},
"SAX_RX5": {
"type": "string"
},
"SAX_RX6": {
"type": "string"
},
"SAX_RX7": {
"type": "string"
},
"SAX_RX8": {
"type": "string"
},
"SAX_RX9": {
"type": "string"
},
"SAX_RY0": {
"type": "string"
},
"SAX_RY1": {
"type": "string"
},
"SAX_RY2": {
"type": "string"
},
"UFI": {
"type": "string"
},
"WID": {
"type": "number"
},
"WPI": {
"type": "string"
},
"ZI001_SDP": {
"type": "string"
},
"ZI001_SDV": {
"type": "string"
},
"ZI001_SPS": {
"type": "integer"
},
"ZI001_SRT": {
"type": "string"
},
"ZI001_VSC": {
"type": "string"
},
"ZI001_VSD": {
"type": "string"
},
"ZI001_VSN": {
"type": "string"
},
"ZI004_RCG": {
"type": "string"
},
"ZI005_FNA": {
"type": "string"
},
"ZI005_FNA2": {
"type": "string"
},
"ZI005_NFN": {
"type": "string"
},
"ZI005_NFN2": {
"type": "string"
},
"ZI006_MEM": {
"type": "string"
},
"ZI020_GE4": {
"type": "string"
},
"ZI026_CTUC": {
"type": "integer"
},
"ZI026_CTUL": {
"type": "integer"
},
"ZI026_CTUU": {
"type": "integer"
},
"ZSAX_RS0": {
"type": "string"
},
"ZSAX_RX0": {
"type": "string"
},
"ZSAX_RX3": {
"type": "string"
},
"ZSAX_RX4": {
"type": "string"
},
"ZVH": {
"type": "number"
},
"FCSUBTYPE": {
"type": "integer"
},
"ADR": {
"type": "string"
},
"LMC": {
"type": "integer"
},
"STL": {
"type": "integer"
},
"STL2": {
"type": "integer"
},
"STL3": {
"type": "integer"
},
"HHD": {
"type": "integer"
}
},
"additionalProperties": false
}
]
},
"links": {
"type": "array",
"items": {
"type": "object",
"required": [
"href"
],
"properties": {
"href": {
"type": "string",
"format": "uri"
},
"rel": {
"type": "string"
},
"type": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
}
4.4.3.3. Property selection
4.4.3.3.1. Overview
Cubeserv implements the properties parameter as defined in OGC API — Features — Part 6: Property Selection.
Cubeserv implements the following conformance classes from OGC API — Features — Part 6: Property Selection:
Table 2 — Conformance class URIs
| Conformance class | URI |
|---|---|
| Property Selection | http://www.opengis.net/spec/ogcapi-features-6/1.0/conf/properties |
| Property Selection (Features) | http://www.opengis.net/spec/ogcapi-features-6/1.0/conf/properties-features |
In addition to the properties parameter, cubeserv also implements an exclude-properties parameter that lists the properties to exclude (rather than include) in the response.
4.4.3.3.2. Examples
{
"type": "Feature",
"id": "CWFID.SETTLEMENTSRF.0.8",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[ 36.33295599, 32.2828885 ], [ 36.33580536, 32.28198786 ],
[ 36.33954522, 32.280714 ], [ 36.3399218, 32.28064846 ],
[ 36.34017809, 32.28070732 ], [ 36.34043842, 32.28088291
], [ 36.34077816, 32.28164959 ], [ 36.34109545, 32.28257287 ],
[ 36.34149681, 32.28395917 ], [ 36.34184168, 32.28532761 ],
[ 36.34209096, 32.2864909 ], [ 36.3422161, 32.28702197 ],
[ 36.34225167, 32.28733591 ], [ 36.34233647, 32.28759259 ],
[ 36.33597433, 32.2896979 ], [ 36.33518813, 32.28802212 ],
[ 36.33513818, 32.28790676 ], [ 36.33418013, 32.28569608 ],
[ 36.33295599, 32.2828885 ]
]
]
},
"properties": {
"CCN": "No Information",
"F_CODE": "AL020",
},
"links": [
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari",
"rel": "service,"
},
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/SettlementSrf?f=application%2Fjson",
"rel": "collection",
"type": "application/json"
},
.
.
.
]
}
Listing 8 — Selecting a sub-set of properties
An equivalent request, using the exclude-properties parameter, that would generate the same response would be:
4.4.3.4. Geometry simplification
4.4.3.4.1. Overview
Cubeserv implements the zoom-level parameter as defined in OGC API — Features — Part 7: Geometry Simplification.
Cubeserv implements the following conformance classes from OGC API — Features — Part 7: Geometry Simplification:
Table 3 — Conformance class URIs
| Conformance class | URI |
|---|---|
| Geometry Simplification | http://www.opengis.net/spec/ogcapi-features-7/1.0/conf/zoom-level |
| Geometry Simplification (Features) | http://www.opengis.net/spec/ogcapi-features-7/1.0/conf/zoom-level-features |
4.4.3.4.2. Examples
{
"type": "Feature",
"id": "CWFID.SETTLEMENTSRF.0.8",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[ 36.33295599, 32.2828885 ], [ 36.33580536, 32.28198786 ],
[ 36.33954522, 32.280714 ], [ 36.3399218, 32.28064846 ],
[ 36.34017809, 32.28070732 ], [ 36.34043842, 32.28088291 ],
[ 36.34077816, 32.28164959 ], [ 36.34109545, 32.28257287 ],
[ 36.34149681, 32.28395917 ], [ 36.34184168, 32.28532761 ],
[ 36.34209096, 32.2864909 ], [ 36.3422161, 32.28702197 ],
[ 36.34225167, 32.28733591 ], [ 36.34233647, 32.28759259 ],
[ 36.33597433, 32.2896979 ], [ 36.33518813, 32.28802212 ],
[ 36.33513818, 32.28790676 ], [ 36.33418013, 32.28569608 ],
[ 36.33295599, 32.2828885 ]
]
]
},
"properties": {
},
"links": [
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari",
"rel": "service,"
},
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/SettlementSrf?f=application%2Fjson",
"rel": "collection",
"type": "application/json"
},
.
.
.
]
}
Listing 9 — An unsimplified geometry
A simplified version of this geometry can be retrieved with:
{
"type": "Feature",
"id": "CWFID.SETTLEMENTSRF.0.8",
geometry": {
"type":"Polygon",
"coordinates": [
[
[ 36.33295599, 32.2828885 ], [ 36.33513818, 32.28790676 ],
[ 36.33418013, 32.28569608 ], [ 36.33295599, 32.2828885 ]
]
]
},
"properties": {
},
"links": [
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari",
"rel": "service,"
},
{
"href": "https://www.pvretano.com/cubewerx/cubeserv/default/ogcapi/zaatari/collections/SettlementSrf?f=application%2Fjson",
"rel": "collection",
"type": "application/json"
},
.
.
.
]
}
Listing 10 — A simplified geometry at zoom level 5
4.4.4. GNOSIS Map Server
New capabilities were integrated in the GNOSIS Map Server during the code sprint, including support for CQL2 advanced spatial operators and WKT geometry, support for filtering map and coverage requests by geometry using CQL2 expressions including WKT geometry, as well as support for the DGGS-JSON data encoding and additional improvements to the implementation of OGC API — DGGS.
In order to support output of DGGS-JSON data, a deterministic ordering of sub-zones needs to be implemented. Progress on the initial design of this scanline based ordering was made at the previous code sprint in Evora, with progress on the implementation since then. During the code sprint, this initial support was deployed.
Figure 27 — Example ordering of ISEA3H sub-zones starting on a vertex for an odd relative depth
Figure 28 — Example ordering of ISEA3H sub-zones starting on an edge for an even relative depth
In addition to the ordering of sub-zones for polar pentagonal zones which was not yet implemented, issues were noticed with parent hexagonal zones crossing interruptions of the Icosahedral Snyder Equal Area planar projection. These issues were identified as new variations of problem which need to be taken into account by the sub-zone ordering algorithm, and work was undertaken to implement these cases correctly. Progress was also made on figuring out the correct sub-zone order of polar pentagonal parent zones.
Figure 29 — Proper ordering for ISEA3H sub-zones of a parent hexagonal zone crossing an ISEA interruption
Figure 30 — Visualization of a DGGS-JSON file generated from the GEBCO_2014 grid
A snippet extract of the DGGS-JSON file used to render this data follows, with the full version available from the OGC API — DGGS implementation at https://maps.gnosis.earth/ogcapi/collections/gebco/dggs/ISEA3H/zones/B2-1-A/data.json?zone-depth=7. The snippet illustrates how the bulk of the encoded data is a simple linearized one-dimensional array of the values associated with each zone, implying a particular order. There is no need to provide the coordinates of the zone geometry, of the centroid, or even the zone identifier for each sub-zone, as this information can be inferred from the zone order.
{
"dggrs" : "https://www.opengis.net/def/dggrs/OGC/1.0/ISEA3H",
"zoneId" : "B2-1-A",
"depths" : [ 7 ],
"values" : {
"Elevation" : [
{
"depth" : 7,
"shape" : { "count" : 2269, "subZones" : 2269 },
"data" : [ -43.212332564804, -49.3541585971952, ..., -5158.8415987109893 ]
}
]
}
}
Listing 11
Figure 31 — DGGS-JSON data representation available from a zone information resource on the GNOSIS Map Server
4.4.5. Geonovum JSON Linter
The team from Geonovum took the existing JSON-FG linter and renamed it to the OGC-Checker. They added functionality to support the OGC API — Features — Part 1: Core Standard and a small portion of the OGC API — Common — Part 1: Core Standard. The tool is now capable of automatically discovering which conformance classes are implemented and can apply the appropriate rulesets for validation based on that. This will enable the maintainers of the tool to add support for other OGC API Standards in the future. Figure 32 shows a screenshot of the linter having validated an instance of the OGC API — Features Standard.
Figure 32 — Screenshot of the JSON Linter
The linter is able to report on any errors that it detects on an implementation. Figure 33 shows a screenshot of an example error message presented by the JSON Linter. In the example, the key servers which is required by the OpenAPI 3.0 Specification has been changed to serves. The linter makes use of Spectral, an open source suite of libraries for testing compliance to the OpenAPI Specification. The linter reports the error on the right hand side of the display.
Figure 33 — Screenshot of an example error message presented by the JSON Linter
Testing the linter on example implementations of OGC API — Features led to the discovery of a number of small issues that were resolved by Clemens Portele (interactive instruments) during the code sprint. With the successful implementation of the linter during the code sprint, the team has taken the first steps toward making the linter/validator more generic. The results can be found here: https://github.com/Geonovum-labs/ogc-checker, a live demo is available here: https://geonovum-labs.github.io/ogc-checker/#/ogc-api
5. Discussion
5.1. MapML
Experimentation with support for MapML proved successful in that multiple applications were extended to enable support for MapML as documented in Clause 4.3.1. Some of the participants commented that the implementation of a simple client web application is where MapML really shines, as it makes it simple for consumers of geospatial data to setup an HTML document with a map and relevant data. The participants also noted that the interactive nature of the MapML viewer gives the user the freedom to reposition a map by panning and zooming. This is a useful capability if the initial loading of map places the map in a location that is different from the location required by a user.
However, the participants also noted that with regard to the work done in order to support MapML on the backend, there seems to be some duplication of effort, which clashes with some of the capabilities found in the OGC API Standards. The adoption of a custom MapML document type, based on XHTML, while appropriate for the frontend, leads to the server having to perform additional serialization of basically the same payloads which are being generated as JSON. This can be seen both in the case of serving MapML tile metadata and also when serving MapML features. This suggests a need to enable future versions of MapML to support JSON-encoded data served by implementations of OGC API Standards.
To make MapML more appealing to developers of server-side software, there should be consideration of how to enable MapML to consume the JSON-based payloads that are described in the OGC API family of standards. This could be an area for future development in a code sprint or other OGC initiative. Since OGC API — Tiles is an approved OGC Standard, formalizing support for OGC API — Tiles within MapML viewers could be a high priority target. Others that could be considered in the long run are OGC API — DGGS and OGC API — GeoDataCubes. All three specifications are concerned with partitioning space and thus could be good candidate direct support in MapML. Support for OGC API — Maps was demonstrated in this code sprint, however this should be expanded in future code sprints with a wider range of applications.
Moving forward, the ease of integrating the MapML viewer into various applications during the code sprint raises the question of how best MapML could be brought into the OGC’s Standards Baseline. Some of the routes that are available to the MapML community include the OGC Community Standard route or the OGC Standard route. It is also noted that OGC and the World Wide Web Consortium (W3C) have a long standing relationship that has produced multiple standards. Both organizations have been supportive of the development of MapML. The requirements and conditions of the different routes to standardization are out of scope of this engineering report, however they are highlighted here for further discussion within the relevant communities.
5.2. Data Quality and Artificial Intelligence
A key element of data quality is a record of how the dataset has been processed, including information about the computational manipulation as well as individuals and organizations who have completed the processing. In ISO 19115, this is described in the lineage classes, and specifically through the LE_Processing Class. This class enables recording of the specific processing and runtime parameters required to create a data quality metric and recreate the lineage if necessary.
OGC has been exploring the use of reusable building blocks to enable elements of standards to be re-used, extended, and modified with a FAIR (Findable, Accessible, Interoperable, Reusable) way. As presented in Clause 4.3.2, the code sprint participants examined the potential use of the ISO 19157-3 data quality measures register to support the documentation of TrainingDML-AI data quality reports. Some of the objectives of the data quality exploration work in this code sprint were to take these concepts to address the following questions:
Can we create machine-readable provenance chains to enable scientific data re-creation?
Can machine-readable provenance chains be automatable, and executable?
Can we use OGC RAINBOW and its building block register to store and refer to mathematical formulae?
Can the formulae be parsed into machine-readable formats, new variables injected, and the provenance chain executed?
The research question “Can we create machine-readable provenance chains to enable scientific data re-creation?” was addressed through the work on pygeoapi. As presented in Clause 4.4.1.1.1, pygeoapi was extended to implement support for ingesting a Common Workflow Language (CWL) definition document in accordance with the OGC API — Processes — Part 2: Deploy, Replace, Undeploy candidate Standard. The successful execution of the CWL workflows through pygeoapi also addressed the research question “Can machine-readable provenance chains be automatable, and executable?”. Finally, the research question “Can we use OGC RAINBOW and its building block register to store and refer to mathematical formulae?” was partly addressed through the creation of data quality reports that referenced RAINBOW-provided definitions containing mathematical formulae as reported in Clause 4.3.2. Unfortunately, it was not possible to inject new variables into the formula to execute the chain for another dataset. Therefore the research question “Can the formulae be parsed into machine-readable formats, new variables injected, and the provenance chain executed?” remains to be answered in future code sprints.
The sprint participants recommended that, in the future, the use cases for machine-readable and executable provenance chains should be widened to include specific ML training data use cases. The ability to sample, correct, and train large datasets should have a reproducible method for training models. The recommendations are as follows:
Run a code sprint focused on machine-readable provenance chains, model reproducibility, and recording data quality.
Update OGC RAINBOW to offer executable code and variable injection to ensure the chains are machine readable.
Test the process with several different datasets with a focus on model reproducibility.
Provide feedback to ISO/TC 211 on findings.
5.3. Relationship between OGC SensorThings API and OGC API — Connected Systems
The code sprint hosted a discussion on the relationship between the OGC SensorThings API Standard and the OGC API — Connected Systems candidate Standard. The purpose of the discussion was to determine the commonalities and differences between the OGC SensorThings API Standard and OGC API – Connected Systems candidate Standard so that a consistent message can be presented to the market. Early in the session, it was observed that collaboration between the SWGs could be improved. It is envisaged therefore that the discussion summarized in this section will help to improve collaboration between the SWGs and consistency in messaging.
The first activity during the session was to review the table of design choices which is presented in Annex B.9 of OGC API — Connected Systems — Part 1: Feature Resources. The table presents a comparison of the design choices made in the development of the two standards. The participants noted that the OGC SensorThings API specifies support for ‘any’ type of observation and thus does not identify a set list of supported observation types. In contrast, OGC API – Connected Systems lists the observation types that the standard supports namely scalar, vector, N-D coverage, and video.
Table 4 — Comparison of design choices made in OGC API — Connected Systems and OGC SensorThings API (reproduced from a draft version of OGC 23-001 on 19 July 2024)
| Design Choice | Connected Systems | SensorThings |
|---|---|---|
| API Platform | Extension of OGC API Common and OGC — API Features. | OData Version 4.0 |
| Query Language | Query string arguments, decoupled from resource encoding. | Generic query language inherited from OData. |
| Resource Model | Based on SOSA/SSN/OMS and SensorML. | Simplified and adapted from O&M. |
| Supported Observation Types | Scalar, vector, N-D coverage, video. | Scalar and simple records only. |
| Multiple Format Support | Yes, including non-JSON such as Protocol Buffers or other binary formats. | OData compatible JSON only. |
The participants noted that rather than focus on how the standards implement certain capabilities, the discussion should instead focus on the use cases that addressed by the standards. There was agreement that use cases would be more appropriate for helping to establish a consistent message to the market. It was noted that several technical and domain use cases are documented in the Reviewers Guide of OGC API – Connected Systems. At the time of the code sprint, the reviewers’ guide offered 25 use cases.
There was an observation made that the ability to identify, describe in detail and integrate different sensor systems is one of the motivations for OGC API – Connected Systems and thus a key differentiator from OGC SensorThings API. That is, as the name suggests, OGC API — Connected Systems is designed to support the deployment and connection of various systems, some of which are likely to include sensors. The domain use cases presented in the Reviewers’ Guide include use cases that highlight this ability to connect different systems.
The key differentiators can therefore be summarized as follows:
The level of complexity of the system(s) and what you need to describe them
How you can query that complexity
Connectivity between the systems
Taking the example of a satellite, the participants explained that an application that required knowledge of where a satellite was, how the satellite was operated, and the resulting observational data would require the capabilities offered by OGC API — Connected Systems. In contrast, an application that only required the resulting observational data and not details of the system collecting the data could be sufficiently supported by an implementation of the OGC SensorThings API.
6. Conclusions
The code sprint provided an environment for the development and testing of prototype implementations of open standards. The in-person participation of several editors of Standards meant that developers could provide feedback to the editors almost instantly. Further, the collaborative environment enabled developers to identify issues in products, fix open issues, develop new product features, improve documentation, and test interoperability with 3rd party products. Furthermore, participants were able to share knowledge in the mentor stream sessions.
Regarding MapML, the participants demonstrated that the current specification of MapML can use implementations of the emerging OGC API — Maps Standard without modification. This engineering report concludes that the sprint participants proved that MapML has a role to play in the geospatial ecosystem and that MapML can be easily integrated into implementations of OGC API Standards. There are several potential avenues for future MapML within the OGC community, on both the innovation and standardization side. Therefore further discussion with the MapML community is needed to help chart a way forward for the specification.
Regarding validators, the engineering report concludes that there is significant potential for client-side validators such as the Linter to enhance the developer experience, alongside server-side validators such as TEAM Engine. Such linters could be offered as a developer resource for those developers that would like to test their products without having the products certified compliant. TEAM Engine, as a server-side application, continues to be the ideal solution for certification of compliance to OGC Standards.
Regarding Data Quality and AI, the engineering report concludes that the use cases for machine readable and executable provenance chains should be widened to include specific ML training data use cases. The ability to sample, correct, and train large datasets should have a reproducible method for training models.
Overall, this engineering report concludes that the code sprint met all of its objectives and achieved its goal of accelerating the development and implementation of OGC Standards in software products. The following subsection presents recommendations for future work.
6.1. Future Work
6.1.1. Experimentation
The sprint participants made the following recommendations regarding potential experiments in future Collaborative Solutions and Innovation (COSI) Program initiatives:
OGC API — 3D Geovolumes experimentation in the context of Digital Twins
CDB2 experimentation in the context of Digital Twins
Experimentation on consistency of metadata frameworks
Experimentation on consistency of parameter and schema fragments in APIs
Experimentation on OGC API — Features and Geocoding
6.1.2. Prototyping
The sprint participants made the following recommendations regarding prototype development in future COSI initiatives:
Initiative on Urban Digital Twins
An activity building on the ISO metadata activity
Prototyping of an HTML MapML validator, possibly as a service. See https://github.com/Maps4HTML/validator-mapml for ideas.
Prototyping of extension of MapML to enable it to consume the JSON-based payloads that are described in the OGC API family of standards
6.1.3. Standardization
The sprint participants made the following recommendations regarding future discussions in working groups and the Standards Program:
Discussion on consistency of parameter and schema fragments in APIs
Development of a roadmap for a possible TrainingDML-AI conformance class for OGC API — Records
Guidance on the consistency of scale between Observations, Measurements, and Samples (OMS) and the API Standards
Addition of a security element in future versions of TrainingDML-AI and other metadata encodings
Run a code sprint focused on machine-readable provenance chains, model reproducibility, and recording data quality.
Update OGC RAINBOW to offer executable code and variable injection to ensure the chains are machine readable.
Test the process of machine-readable provenance chains with several different datasets with a focus on model reproducibility.
Provide feedback to ISO/TC 211 on findings regarding Data Quality and AI.
Bibliography
[1] Mark Burgoyne, David Blodgett, Charles Heazel, Chris Little: OGC 19-086r6, OGC API — Environmental Data Retrieval Standard. Open Geospatial Consortium (2023). http://www.opengis.net/doc/IS/ogcapi-edr-1/1.1.0.
[2] Clemens Portele, Panagiotis (Peter) A. Vretanos, Charles Heazel: OGC 17-069r4, OGC API — Features — Part 1: Core corrigendum. Open Geospatial Consortium (2022). http://www.opengis.net/doc/IS/ogcapi-features-1/1.0.1.
[3] Clemens Portele, Panagiotis (Peter) A. Vretanos: OGC 18-058r1, OGC API — Features — Part 2: Coordinate Reference Systems by Reference corrigendum. Open Geospatial Consortium (2022). http://www.opengis.net/doc/IS/ogcapi-features-2/1.0.1.
[4] Benjamin Pross, Panagiotis (Peter) A. Vretanos: OGC 18-062r2, OGC API — Processes — Part 1: Core. Open Geospatial Consortium (2021). http://www.opengis.net/doc/IS/ogcapi-processes-1/1.0.0.
[5] Joan Masó, Jérôme Jacovella-St-Louis: OGC 20-057, OGC API — Tiles — Part 1: Core. Open Geospatial Consortium (2022). http://www.opengis.net/doc/IS/ogcapi-tiles-1/1.0.0.
[6] Steve Liang, Tania Khalafbeigi, Hylke van der Schaaf: OGC 18-088, OGC SensorThings API Part 1: Sensing Version 1.1. Open Geospatial Consortium (2021). http://www.opengis.net/doc/is/sensorthings/1.1.0.
[7] ISO: ISO 19135-1:2015, Geographic information — Procedures for item registration — Part 1: Fundamentals. International Organization for Standardization, Geneva (2015). https://www.iso.org/standard/54721.html.
[8] ISO: ISO 19157-1:2023, Geographic information — Data quality — Part 1: General requirements. International Organization for Standardization, Geneva (2023). https://www.iso.org/standard/78900.html.
[9] ISO/AWI: ISO/AWI 19157-3, ISO: ISO/AWI 19157-3 Geographic information — Data quality — Part 3: Data quality measures register (Draft).. ISO, AWI
[10] OGC: OGC API — Connected Systems — Part 1: Feature Resources (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/23-001r0.html
[11] OGC: OGC API — Coverages — Part 1: Core (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/19-087.html
[12] OGC: OGC API — Discrete Global Grid Systems — Part 1: Core (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/21-038.html
[13] OGC: OGC API — Environmental Data Retrieval — Part 2: Publish-Subscribe Workflow (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/23-057.html
[14] OGC: OGC API — Maps — Part 1: Core (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/20-058.html
[15] OGC: OGC API — Records — Part 1: Core (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/20-004.html
[16] OGC: OGC Cartographic Symbology — Part 1: Core Model & Encodings (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/18-067r4.html
[17] OGC: OGC Features and Geometries JSON — Part 1: Core (draft), Open Geospatial Consortium. https://docs.ogc.org/DRAFTS/21-045r1.html
[18] Peter Rushforth: Map Markup Language — Draft Community Group Report, Maps For HTML Community Group. https://maps4html.org/MapML/spec
Annex A
(informative)
Example Use of Model Driven Standards with OGC API — Common
This appendix presents a use of the Model Driven Standards (MDS) approach described in the OGC Guidance for the Development of Model-Driven Standards Discussion Paper (OGC 23-040).
The appendix is added here as input into future code sprints, which are expected to increasingly use MDS as the more editors and developers become familiar with the approach.
A.1. OGC API — Common package
A.1.1. OGC API — Common overview
Figure A.1 — Part 2 Classes
A.1.2. Defining tables
Table A.1 — Elements of “OGC API — Common::CollectionDesc” (type)
| Name: | CollectionDesc | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Description of a collection | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Extent-UAD | Extent-UAD | ||||||
Link | M | * | Link | ||||
Collections | Collections | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
id | M | 1 | |||||
title | C | 1 | |||||
description | C | 1 | |||||
attribution | C | 1 | |||||
itemType | C | 1 | |||||
crs | C | 1 | |||||
storageCrs | C | 1 | |||||
dataType | M | 1 | |||||
geometryDimension | C | 1 | |||||
minScaleDenominator | C | 1 | |||||
maxScaleDenominator | C | 1 | |||||
minCellSize | C | 1 | |||||
maxCellSize | C | 1 | |||||
| Constraints: | (none) | ||||||
Table A.2 — Elements of “OGC API — Common::Collections” (type)
| Name: | Collections | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | A set of geospatial resources that may be available as one or more sub-resource distributions that conform to one or more OGC API standards. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Link | M | * | Link | ||||
CollectionDesc | M | * | CollectionDesc | ||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
timeStamp | C | 1 | |||||
numberMatched | C | 1 | |||||
numberReturned | C | 1 | |||||
| Constraints: | (none) | ||||||
Table A.3 — Elements of “OGC API — Common::ConfClasses” (type)
| Name: | ConfClasses | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | A declaration of conformance classes that the API conforms to | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | (none) | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
conformsTo | A list all OGC API conformance classes that the API conforms to | M | * | ||||
| Constraints: | (none) | ||||||
Table A.4 — Elements of “OGC API — Common::Enumeration” (type)
| Name: | Enumeration | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | An enumerated list of valid string values. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | (none) | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
type | M | 1 | |||||
enum | M | * | |||||
| Constraints: | (none) | ||||||
Table A.5 — Elements of “OGC API — Common::Exception” (type)
| Name: | Exception | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | A schema for exceptions based on RFC 7807 | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | (none) | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
type | M | * | |||||
title | M | 1 | |||||
status | M | 1 | |||||
detail | M | 1 | |||||
instance | M | 1 | |||||
| Constraints: | (none) | ||||||
Table A.6 — Elements of “OGC API — Common::Extent” (type)
| Name: | Extent | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | The extent of the data in the collection. In the Core only spatial and temporal extents are specified. Extensions may add additional members to represent other extents, for example, thermal or pressure ranges. The first item in the array describes the overall extent of the data. All subsequent items describe more precise extents, e.g., to identify clusters of data. Clients only interested in the overall extent will only need to access the first item in each array. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
SpatialExtent | SpatialExtent | ||||||
TemporalExtent | TemporalExtent | ||||||
Extent-UAD | Extent-UAD | ||||||
| Public attributes: | (none) | ||||||
| Constraints: | (none) | ||||||
Table A.7 — Elements of “OGC API — Common::Extent-UAD” (type)
| Name: | Extent-UAD | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Extent with Uniform Additional Dimensions Schema | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Grid | Grid | ||||||
Extent | Extent | ||||||
CollectionDesc | CollectionDesc | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
interval | M | 2 | |||||
trs | M | 1 | |||||
vrs | M | 1 | |||||
definition | M | 1 | |||||
unit | M | 1 | |||||
unitlang | M | 1 | |||||
| Constraints: | (none) | ||||||
Table A.8 — Elements of “OGC API — Common::Grid” (type)
| Name: | Grid | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Provides information about the limited availability of data within the collection organized as a grid (regular or irregular) along the dimension. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
TemporalExtent | TemporalExtent | ||||||
Extent-UAD | Extent-UAD | ||||||
SpatialExtent | SpatialExtent | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
coordinates | M | * | |||||
cellsCount | C | 1 | |||||
resolution | C | 1 | |||||
| Constraints: | (none) | ||||||
Table A.9 — Elements of “OGC API — Common::Items” (type)
| Name: | Items | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Items in an array | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
SpatialExtent | SpatialExtent | ||||||
SpatialExtent | SpatialExtent | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
items | 6 | ||||||
| Constraints: | (none) | ||||||
Table A.10 — Elements of “OGC API — Common::LandingPage” (type)
| Name: | LandingPage | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | A page that serves as the root node of the API Resource tree and provides the information needed to navigate all the resources exposed through the API. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | (none) | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
title | The title of the API | M | * | ||||
description | a description of the API | C | 1 | ||||
attribution | attribution for the API | C | 1 | ||||
links | M | 1 | |||||
| Constraints: | (none) | ||||||
Table A.11 — Elements of “OGC API — Common::Link” (type)
| Name: | Link | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | An expression of a relationship between resources. | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Collections | Collections | ||||||
CollectionDesc | CollectionDesc | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
href | M | 1 | |||||
rel | M | 1 | |||||
type | C | 1 | |||||
hreflang | C | 1 | |||||
title | C | 1 | |||||
length | C | 1 | |||||
| Constraints: | (none) | ||||||
Table A.12 — Elements of “OGC API — Common::SpatialExtent” (type)
| Name: | SpatialExtent | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Spatial extent | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Items | Items | ||||||
Items | Items | ||||||
Grid | Grid | ||||||
Extent | Extent | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
crs | M | 1 | |||||
| Constraints: | (none) | ||||||
Table A.13 — Elements of “OGC API — Common::TemporalExtent” (type)
| Name: | TemporalExtent | ||||||
|---|---|---|---|---|---|---|---|
| Definition: | Temporal extent | ||||||
| Stereotype: | type | ||||||
| Abstract: | False | ||||||
| Associations: | Association with | Obligation | Maximum occurrence | Provides | |||
Grid | Grid | ||||||
Extent | Extent | ||||||
| Public attributes: | Name | Definition | Derived | Obligation | Maximum occurrence | Data type | |
trs | M | 1 | |||||
| Constraints: | (none) | ||||||
Annex B
(informative)
Revision History
Table — Revision History
| Date | Release | Author | Primary clauses modified | Description |
|---|---|---|---|---|
| 2024-07-11 | 0.1 | G. Hobona | all | initial version |
| 2024-07-14 | 0.2 | T. Kralidis | all | OSGeo updates |