ogcopenapis 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/README.md +158 -92
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to ogcopenapis are in this file. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Each pull request adds its changes under Unreleased. A release renames Unreleased to its version and date.
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [1.0.2] - 2026-10-27
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- The README examples take every value from the capabilities: the formats of the links, the CRS of a map (the
|
|
15
|
+
reference of the map when the collection offers it, otherwise CRS84), the tileset in the reference of the map, the
|
|
16
|
+
styles for its tile matrix set, and the extents. The examples are functions that run as written; two of them failed on
|
|
17
|
+
servers whose links have no type or whose tilesets list no URI.
|
|
18
|
+
- Demo: the CRS of a map and the encoding of features come from the capabilities, and a tileset bounding box without a
|
|
19
|
+
CRS is not taken as CRS84.
|
|
20
|
+
|
|
21
|
+
## [1.0.1] - 2026-10-27
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- The Features example of the README keeps the feature ids of the server, `new GeoJsonCodec({generateIDs: false})`.
|
|
25
|
+
`generateIDs: true` replaced them with ids of its own on every query: `get(id)` of the store then requested ids that
|
|
26
|
+
do not exist, and LuciadRIA re-added every feature on every query. The library is unchanged, the application passes
|
|
27
|
+
the codec.
|
|
28
|
+
|
|
29
|
+
## [1.0.0] - 2026-10-27
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **BREAKING:** requires LuciadRIA 2026.1 or higher, as a peer dependency: the application installs its single copy,
|
|
33
|
+
the package never bundles it.
|
|
34
|
+
- **BREAKING:** the package is native ES modules (`"type": "module"`) with an `exports` map. Import components as
|
|
35
|
+
`ogcopenapis/OgcOpenApiFeatureStore`, the paths of 0.0.12 with `lib/` still work. TypeScript projects need
|
|
36
|
+
`moduleResolution` `bundler`, `node16` or `nodenext` for the paths without `lib/`.
|
|
37
|
+
- OgcOpenApiTilesModel uses LuciadRIA's WMTS support: create it with `createFromTileSet`, which handles tile matrix
|
|
38
|
+
sets that are not quad-trees and `tileMatrixSetLimits`.
|
|
39
|
+
- OgcOpenApiFeatureStore extends LuciadRIA's `Store`. Its requests always settle, and it supports `abortSignal`.
|
|
40
|
+
- `fetchTileSetsInFull` leaves out tile matrix sets whose definition cannot be read, instead of failing, and rejects
|
|
41
|
+
only when none can be read.
|
|
42
|
+
- OgcOpenApiMapsModel keeps the `f` value of the map link, such as `f=png`, and encodes its query.
|
|
43
|
+
- Tile matrix set definitions are requested by their link as the server gives it, with an `Accept: application/json`
|
|
44
|
+
header.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
- Vector tiles (Mapbox Vector Tiles): OgcOpenApiVectorTilesModel, on LuciadRIA's MapboxVectorTileSetModel. It reads
|
|
48
|
+
the layers from a few tiles when a tileset does not list them (`discoverLayers`).
|
|
49
|
+
- OGC API Styles in the Mapbox GL encoding: OgcOpenApiStyleTools, with a stylesheet or a style per tile matrix set
|
|
50
|
+
(`pickStylesheet`, `getStylesForTileMatrixSet`) and a generated default style (`createDefaultStyle`).
|
|
51
|
+
- The tilesets of a collection, only the tile matrix sets it is tiled in: `fetchCollectionTileSets`, matched to the
|
|
52
|
+
tile matrix sets of the server by URI (`matchTileMatrixSet`, `fetchTileMatrixSetOfTileSet`).
|
|
53
|
+
- The tilesets of the dataset, all collections in each tile: `hasDatasetTileSets`, `fetchDatasetTileSets`, and
|
|
54
|
+
`fetchCollectionTileSet` with collection `null`.
|
|
55
|
+
- A tile matrix set included in a tileset is used as is.
|
|
56
|
+
- A demo, test servers with recorded, live and browser tests, and a check of the package as published.
|
|
57
|
+
|
|
58
|
+
### Deprecated
|
|
59
|
+
- The constructor `new OgcOpenApiTilesModel(options)`: it supports quad-tree tile matrix sets only.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
- Relative links are resolved against the URL of their document, instead of the host of the server.
|
|
63
|
+
- Tile matrix set URIs match regardless of `http`/`https`, the case of the host and a trailing slash.
|
|
64
|
+
- `orderedAxes` `Y, X` (EPSG:3035) is northing first: `pointOfOrigin` is read in that order.
|
|
65
|
+
- `fromURL` without options no longer hangs.
|
|
66
|
+
|
|
67
|
+
## 0.0.12 and earlier
|
|
68
|
+
|
|
69
|
+
See the [git history](https://github.com/felipecarrillo100/ogcopenapis/commits/main).
|
|
70
|
+
|
|
71
|
+
[Unreleased]: https://github.com/felipecarrillo100/ogcopenapis/compare/v1.0.2...HEAD
|
|
72
|
+
[1.0.2]: https://github.com/felipecarrillo100/ogcopenapis/compare/v1.0.1...v1.0.2
|
|
73
|
+
[1.0.1]: https://github.com/felipecarrillo100/ogcopenapis/compare/v1.0.0...v1.0.1
|
|
74
|
+
[1.0.0]: https://github.com/felipecarrillo100/ogcopenapis/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ npm run test:record
|
|
|
63
63
|
GNOSIS (https://maps.gnosis.earth/ogcapi/) is in the list but not tested: its `/collections` response is 9 MB, and its tiles need a login.
|
|
64
64
|
|
|
65
65
|
The package check builds and packs the package, and checks it as published: only `lib/`, the sources of its source
|
|
66
|
-
maps, README, LICENSE and package.json are in it, nothing of LuciadRIA; `lib/` imports only its own modules and
|
|
66
|
+
maps, README, CHANGELOG, LICENSE and package.json are in it, nothing of LuciadRIA; `lib/` imports only its own modules and
|
|
67
67
|
`@luciad/ria`; [publint](https://publint.dev) and [Are the Types Wrong](https://arethetypeswrong.github.io) find no
|
|
68
68
|
problems; and every module loads through the package exports, installed in a `node_modules` folder, by Node's own
|
|
69
69
|
ES module loader, as in the tests of an application:
|
|
@@ -100,12 +100,15 @@ The package is native ES modules. Import each component by its name, `ogcopenapi
|
|
|
100
100
|
instance. The paths of version 0.0.12, `ogcopenapis/lib/OgcOpenApiFeatureStore`, still work.
|
|
101
101
|
|
|
102
102
|
### Capabilities
|
|
103
|
-
`fromURL` reads the landing page of a server and its collections, optionally only those with links of one type
|
|
103
|
+
`fromURL` reads the landing page of a server and its collections, optionally only those with links of one type. Everything
|
|
104
|
+
the examples below need comes from these capabilities: links and their formats, extents, the CRSs a collection offers,
|
|
105
|
+
tilesets, tile matrix sets and styles. Nothing is configured by hand.
|
|
104
106
|
```typescript
|
|
105
107
|
import {CollectionLinkType, OgcOpenApiGetCapabilities} from "ogcopenapis/OgcOpenApiGetCapabilities";
|
|
106
108
|
|
|
107
|
-
const capabilities = await OgcOpenApiGetCapabilities.fromURL(
|
|
108
|
-
|
|
109
|
+
const capabilities = await OgcOpenApiGetCapabilities.fromURL(serverUrl, {filterCollectionsByLinkType: CollectionLinkType.Items});
|
|
110
|
+
// The collections, as the server lists them: id, title, extent, crs and links
|
|
111
|
+
const collection = capabilities.collections.find(c => c.id === collectionId);
|
|
109
112
|
```
|
|
110
113
|
Links that are relative are resolved against the document that has them.
|
|
111
114
|
|
|
@@ -116,6 +119,19 @@ const proxify = (url: string, fetchOptions: RequestInit) => ({url: "https://prox
|
|
|
116
119
|
const capabilities = await OgcOpenApiGetCapabilities.fromURL(serverUrl, {proxify});
|
|
117
120
|
```
|
|
118
121
|
|
|
122
|
+
The examples below share these imports and constants:
|
|
123
|
+
```typescript
|
|
124
|
+
import type {Map} from "@luciad/ria/view/Map.js";
|
|
125
|
+
import {getReference} from "@luciad/ria/reference/ReferenceProvider.js";
|
|
126
|
+
import {
|
|
127
|
+
CollectionLinkType, OgcOpenApiCapabilitiesCollection, OgcOpenApiCapabilitiesObject, OgcOpenApiGetCapabilities,
|
|
128
|
+
CollectionTileSet, CollectionTileSetInfo, TileSetData
|
|
129
|
+
} from "ogcopenapis/OgcOpenApiGetCapabilities";
|
|
130
|
+
import {OgcOpenApiCrsTools} from "ogcopenapis/OgcOpenApiCrsTools";
|
|
131
|
+
|
|
132
|
+
const CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84";
|
|
133
|
+
```
|
|
134
|
+
|
|
119
135
|
### Features
|
|
120
136
|
OgcOpenApiFeatureStore implements a LuciadRIA store, to use with FeatureModel and FeatureLayer:
|
|
121
137
|
```typescript
|
|
@@ -123,116 +139,175 @@ import {FeatureModel} from "@luciad/ria/model/feature/FeatureModel.js";
|
|
|
123
139
|
import {FeatureLayer} from "@luciad/ria/view/feature/FeatureLayer.js";
|
|
124
140
|
import {LoadSpatially} from "@luciad/ria/view/feature/loadingstrategy/LoadSpatially.js";
|
|
125
141
|
import {GeoJsonCodec} from "@luciad/ria/model/codec/GeoJsonCodec.js";
|
|
126
|
-
import {getReference} from "@luciad/ria/reference/ReferenceProvider.js";
|
|
127
142
|
import {OgcOpenApiFeatureStore} from "ogcopenapis/OgcOpenApiFeatureStore";
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
function createFeatureLayer(collection: OgcOpenApiCapabilitiesCollection) {
|
|
145
|
+
const items = OgcOpenApiGetCapabilities.filterCollectionLinks(collection.links, CollectionLinkType.Items);
|
|
146
|
+
// GeoJSON, the encoding that GeoJsonCodec reads
|
|
147
|
+
const link = items.find(l => l.type === "application/geo+json") || items.find(l => l.type === "application/json");
|
|
148
|
+
if (!link) throw new Error("Collection " + collection.id + " has no GeoJSON items");
|
|
149
|
+
// CRS84: OGC API Features requires every server to support it
|
|
150
|
+
const crs = CRS84;
|
|
151
|
+
const store = new OgcOpenApiFeatureStore({
|
|
152
|
+
dataUrl: link.href,
|
|
153
|
+
outputFormat: link.type,
|
|
154
|
+
// The ids of the server: get(id) requests items/{id} with them
|
|
155
|
+
codec: new GeoJsonCodec({generateIDs: false}),
|
|
156
|
+
crs,
|
|
157
|
+
extent: collection.extent,
|
|
158
|
+
useCrs84Bounds: true,
|
|
159
|
+
});
|
|
160
|
+
const model = new FeatureModel(store, {reference: getReference(OgcOpenApiCrsTools.getReferenceName(crs))});
|
|
161
|
+
return new FeatureLayer(model, {label: collection.title || collection.id, loadingStrategy: new LoadSpatially()});
|
|
162
|
+
}
|
|
140
163
|
```
|
|
141
164
|
The store requests the features in view, a query does not follow the `next` links of a response yet (no paging).
|
|
142
165
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
Keep the ids of the server: `generateIDs: false`. Each feature of an OGC API Features collection has an id, `get(id)` of
|
|
167
|
+
the store requests `items/{id}` with it, and LuciadRIA updates only the features that changed when the ids stay the same
|
|
168
|
+
between queries. `generateIDs: true` replaces them with ids of its own on every query.
|
|
146
169
|
|
|
147
|
-
|
|
170
|
+
### Maps
|
|
171
|
+
OgcOpenApiMapsModel extends WMSTileSetModel, use it with a RasterTileSetLayer. It requests the map as tiles, in the
|
|
172
|
+
reference of the map when the collection offers it, otherwise in CRS84, which every server supports, and LuciadRIA
|
|
173
|
+
reprojects it:
|
|
148
174
|
```typescript
|
|
149
175
|
import {RasterTileSetLayer} from "@luciad/ria/view/tileset/RasterTileSetLayer.js";
|
|
150
176
|
import {OgcOpenApiMapsModel} from "ogcopenapis/OgcOpenApiMapsModel";
|
|
151
177
|
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
178
|
+
function createMapLayer(map: Map, collection: OgcOpenApiCapabilitiesCollection) {
|
|
179
|
+
const mapLinks = OgcOpenApiGetCapabilities.filterCollectionLinks(collection.links, CollectionLinkType.Map);
|
|
180
|
+
// PNG, with transparency, when the server types its links. The link carries the f value the server accepts
|
|
181
|
+
const link = mapLinks.find(l => l.type === "image/png") || mapLinks[0];
|
|
182
|
+
if (!link) throw new Error("Collection " + collection.id + " has no map");
|
|
183
|
+
const crs = (collection.crs || []).find(c => OgcOpenApiCrsTools.getReferenceName(c) === map.reference.identifier) || CRS84;
|
|
184
|
+
const model = new OgcOpenApiMapsModel({crs, baseURL: link.href, collection: collection.id});
|
|
185
|
+
return new RasterTileSetLayer(model, {label: collection.title || collection.id});
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Tilesets
|
|
190
|
+
Map tiles and vector tiles start from the tilesets: of a collection, or of the dataset (`collection` null), all its
|
|
191
|
+
collections in each tile. Each tileset is in one tile matrix set. Servers give tile matrix sets their own ids (CubeWerx
|
|
192
|
+
calls WebMercatorQuad `smerc`), `fetchTileMatrixSetOfTileSet` matches them by URI.
|
|
193
|
+
```typescript
|
|
194
|
+
import {OgcOpenApiTileMatrixTools} from "ogcopenapis/OgcOpenApiTileMatrixTools";
|
|
195
|
+
|
|
196
|
+
interface UsableTileSet {
|
|
197
|
+
tileSet: CollectionTileSetInfo;
|
|
198
|
+
tileMatrix: TileSetData;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// The tilesets that LuciadRIA can use, each with its tile matrix set. Left out: tile matrix sets in a reference that is
|
|
202
|
+
// not registered (see References below), and for vector tiles those that LuciadRIA cannot address as a quad-tree
|
|
203
|
+
async function fetchUsableTileSets(capabilities: OgcOpenApiCapabilitiesObject, collection: OgcOpenApiCapabilitiesCollection | null, linkType: CollectionLinkType) {
|
|
204
|
+
// fetchTileSetsInFull leaves out definitions that cannot be read, it rejects only when none can
|
|
205
|
+
const tileMatrixSets = await OgcOpenApiGetCapabilities.fetchTileSetsInFull(capabilities);
|
|
206
|
+
const tileSets = collection ?
|
|
207
|
+
await OgcOpenApiGetCapabilities.fetchCollectionTileSets(capabilities, collection, linkType) :
|
|
208
|
+
await OgcOpenApiGetCapabilities.fetchDatasetTileSets(capabilities, linkType);
|
|
209
|
+
const usable = await Promise.all(tileSets.map(async (tileSet): Promise<UsableTileSet | null> => {
|
|
210
|
+
try {
|
|
211
|
+
const tileMatrix = await OgcOpenApiGetCapabilities.fetchTileMatrixSetOfTileSet(capabilities, tileSet, tileMatrixSets);
|
|
212
|
+
const grid = OgcOpenApiTileMatrixTools.createTileGrid(tileMatrix);
|
|
213
|
+
return linkType === CollectionLinkType.VectorTiles && grid.levelCount <= 1 ? null : {tileSet, tileMatrix};
|
|
214
|
+
} catch (e) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}));
|
|
218
|
+
return usable.filter(t => t !== null);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The tileset in the reference of the map, which needs no reprojection, otherwise the first one
|
|
222
|
+
function pickTileSet(map: Map, tileSets: UsableTileSet[]) {
|
|
223
|
+
if (tileSets.length === 0) throw new Error("No tileset in a tile matrix set that LuciadRIA can use");
|
|
224
|
+
return tileSets.find(t => OgcOpenApiCrsTools.getReferenceName(t.tileMatrix.crs) === map.reference.identifier) || tileSets[0];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Where the data is, in CRS84 as [minX, minY, maxX, maxY]: the extent of the collection, or for the dataset the
|
|
228
|
+
// bounding box of the tileset, when the server gives them in CRS84
|
|
229
|
+
function getExtent(collection: OgcOpenApiCapabilitiesCollection | null, tileSet: CollectionTileSet): number[] | undefined {
|
|
230
|
+
if (collection) {
|
|
231
|
+
const spatial = collection.extent && collection.extent.spatial;
|
|
232
|
+
return spatial && spatial.bbox && (!spatial.crs || /CRS84$/.test(spatial.crs)) ? spatial.bbox[0] : undefined;
|
|
233
|
+
}
|
|
234
|
+
const box = tileSet.boundingBox;
|
|
235
|
+
return box && box.crs && /CRS84$/.test(box.crs) ? [...box.lowerLeft, ...box.upperRight] : undefined;
|
|
236
|
+
}
|
|
159
237
|
```
|
|
160
238
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
239
|
+
### Map tiles
|
|
240
|
+
OgcOpenApiTilesModel extends WMTSTileSetModel, use it with a RasterTileSetLayer. Create it with `createFromTileSet`: it
|
|
241
|
+
describes the tileset to LuciadRIA's WMTS support, which handles tile matrix sets that are quad-trees and tile matrix sets
|
|
242
|
+
that are not (such as GlobalCRS84Scale), and it does not request tiles outside the `tileMatrixSetLimits`:
|
|
164
243
|
```typescript
|
|
165
244
|
import {OgcOpenApiTilesModel} from "ogcopenapis/OgcOpenApiTilesModel";
|
|
166
245
|
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
246
|
+
async function createTileLayer(map: Map, capabilities: OgcOpenApiCapabilitiesObject, collection: OgcOpenApiCapabilitiesCollection | null) {
|
|
247
|
+
const {tileSet: tileSetInfo, tileMatrix} = pickTileSet(map, await fetchUsableTileSets(capabilities, collection, CollectionLinkType.Tiles));
|
|
248
|
+
const tileSet = await OgcOpenApiGetCapabilities.fetchCollectionTileSet(capabilities, collection, tileSetInfo, {}, CollectionLinkType.Tiles);
|
|
249
|
+
// PNG, with transparency, when the server types its links
|
|
250
|
+
const link = tileSet.links.find(l => l.type === "image/png") || tileSet.links[0];
|
|
251
|
+
const model = await OgcOpenApiTilesModel.createFromTileSet({
|
|
252
|
+
tileMatrix,
|
|
253
|
+
baseURL: link.href,
|
|
254
|
+
collection: collection ? collection.id : "dataset",
|
|
255
|
+
format: link.type && link.type.indexOf("image/") === 0 ? link.type : undefined,
|
|
256
|
+
tileMatrixSetLimits: tileSet.tileMatrixSetLimits,
|
|
257
|
+
extent: getExtent(collection, tileSet),
|
|
258
|
+
});
|
|
259
|
+
return new RasterTileSetLayer(model, {label: collection ? collection.title || collection.id : "All collections"});
|
|
260
|
+
}
|
|
176
261
|
```
|
|
177
262
|
The constructor `new OgcOpenApiTilesModel(options)` still works, but is deprecated: it supports quad-tree tile matrix sets only.
|
|
178
|
-
Look at the LuciadRIA documentation if you need further information on using RasterTileSetLayer.
|
|
179
263
|
|
|
180
264
|
### Vector tiles
|
|
181
|
-
|
|
182
|
-
|
|
265
|
+
OgcOpenApiVectorTilesModel extends LuciadRIA's MapboxVectorTileSetModel, use it with a MapboxVectorTileSetLayer and a
|
|
266
|
+
MapboxStyle. The style is one of the server (OGC API Styles) for the tile matrix set in use, or a style generated from
|
|
267
|
+
the layers in the tiles when the server has none:
|
|
183
268
|
```typescript
|
|
184
269
|
import {MapboxVectorTileSetLayer} from "@luciad/ria/view/mapbox/MapboxVectorTileSetLayer.js";
|
|
185
270
|
import {MapboxStyle} from "@luciad/ria/view/mapbox/MapboxStyle.js";
|
|
186
|
-
import {CollectionLinkType, OgcOpenApiGetCapabilities} from "ogcopenapis/OgcOpenApiGetCapabilities";
|
|
187
271
|
import {OgcOpenApiVectorTilesModel} from "ogcopenapis/OgcOpenApiVectorTilesModel";
|
|
188
272
|
import {OgcOpenApiStyleTools} from "ogcopenapis/OgcOpenApiStyleTools";
|
|
189
273
|
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const layers = tileSet.layers.length > 0 ? tileSet.layers : await model.discoverLayers({extent: collection
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
map.layerTree.addChild(new MapboxVectorTileSetLayer(model, {label: collection.title, style: MapboxStyle.createFromObject(styleJson)}));
|
|
274
|
+
async function createVectorTileLayer(map: Map, capabilities: OgcOpenApiCapabilitiesObject, collection: OgcOpenApiCapabilitiesCollection | null) {
|
|
275
|
+
const tileSets = await fetchUsableTileSets(capabilities, collection, CollectionLinkType.VectorTiles);
|
|
276
|
+
const {tileSet: tileSetInfo, tileMatrix} = pickTileSet(map, tileSets);
|
|
277
|
+
const tileSet = await OgcOpenApiGetCapabilities.fetchCollectionTileSet(capabilities, collection, tileSetInfo, {}, CollectionLinkType.VectorTiles);
|
|
278
|
+
// Mapbox Vector Tiles, the vector tile encoding LuciadRIA reads
|
|
279
|
+
const link = tileSet.links.find(l => l.type === "application/vnd.mapbox-vector-tile") || tileSet.links.find(l => !l.type);
|
|
280
|
+
if (!link) throw new Error("The tileset has no Mapbox Vector Tiles");
|
|
281
|
+
const label = collection ? collection.title || collection.id : "All collections";
|
|
282
|
+
const model = new OgcOpenApiVectorTilesModel({
|
|
283
|
+
tileMatrix,
|
|
284
|
+
baseURL: link.href,
|
|
285
|
+
collection: collection ? collection.id : "dataset",
|
|
286
|
+
tileMatrixSetLimits: tileSet.tileMatrixSetLimits,
|
|
287
|
+
});
|
|
288
|
+
// The styles of the collection, or of the dataset, for this tile matrix set. An application can let the user pick one
|
|
289
|
+
const styles = OgcOpenApiStyleTools.getStylesForTileMatrixSet(
|
|
290
|
+
await OgcOpenApiStyleTools.fetchStyles(capabilities, collection), tileMatrix.id, tileSets.map(t => t.tileMatrix.id));
|
|
291
|
+
let styleJson;
|
|
292
|
+
if (styles.length > 0) {
|
|
293
|
+
styleJson = await OgcOpenApiStyleTools.fetchMapboxStyle(capabilities, OgcOpenApiStyleTools.pickStylesheet(styles[0], tileMatrix.id));
|
|
294
|
+
} else {
|
|
295
|
+
// The layers in the tiles: from the tileset, or read from a few tiles where the data is
|
|
296
|
+
const layers = tileSet.layers.length > 0 ? tileSet.layers : await model.discoverLayers({extent: getExtent(collection, tileSet)});
|
|
297
|
+
styleJson = OgcOpenApiStyleTools.createDefaultStyle(layers, label);
|
|
298
|
+
}
|
|
299
|
+
return new MapboxVectorTileSetLayer(model, {label, style: MapboxStyle.createFromObject(styleJson)});
|
|
300
|
+
}
|
|
218
301
|
```
|
|
219
302
|
|
|
220
303
|
### Tiles of the dataset
|
|
221
304
|
Some servers tile the dataset as a whole, with all its collections in each tile, and some only the dataset (PDOK).
|
|
222
|
-
The tilesets and styles of the dataset are linked from the landing page:
|
|
223
|
-
|
|
305
|
+
The tilesets and styles of the dataset are linked from the landing page. The functions above take `null` for them:
|
|
224
306
|
```typescript
|
|
225
307
|
if (OgcOpenApiGetCapabilities.hasDatasetTileSets(capabilities, CollectionLinkType.VectorTiles)) {
|
|
226
|
-
|
|
227
|
-
const tileMatrix = await OgcOpenApiGetCapabilities.fetchTileMatrixSetOfTileSet(capabilities, datasetTileSets[0], tileMatrixSets);
|
|
228
|
-
// null instead of a collection: the tileset of the dataset
|
|
229
|
-
const tileSet = await OgcOpenApiGetCapabilities.fetchCollectionTileSet(capabilities, null, datasetTileSets[0], {}, CollectionLinkType.VectorTiles);
|
|
230
|
-
// The styles of the dataset, only those for the tile matrix set in use
|
|
231
|
-
const datasetStyles = OgcOpenApiStyleTools.getStylesForTileMatrixSet(
|
|
232
|
-
await OgcOpenApiStyleTools.fetchStyles(capabilities, null), tileMatrix.id, [tileMatrix.id /* and the ids of the other tilesets */]);
|
|
308
|
+
map.layerTree.addChild(await createVectorTileLayer(map, capabilities, null));
|
|
233
309
|
}
|
|
234
310
|
```
|
|
235
|
-
A tileset of the dataset can have a `boundingBox`, where its data is. A collection has its `extent` instead.
|
|
236
311
|
|
|
237
312
|
### Styles
|
|
238
313
|
* LuciadRIA reads the Mapbox GL encoding of OGC API Styles only, not SLD or other encodings.
|
|
@@ -291,17 +366,8 @@ which MapEvolution uses) do. The WKT of epsg.io that the demo uses has no `AXIS`
|
|
|
291
366
|
level 0, and does not request tiles outside the `tileMatrixSetLimits` of the tileset.
|
|
292
367
|
* LuciadRIA 2026.1.1 does not paint Mapbox `circle` layers. The default style draws points as a text symbol for that reason.
|
|
293
368
|
|
|
294
|
-
## Changes
|
|
295
|
-
|
|
296
|
-
* It requires LuciadRIA 2026.1 or higher, as a peer dependency: the application installs it.
|
|
297
|
-
* The package is native ES modules (`"type": "module"`), with an `exports` map. Import components as
|
|
298
|
-
`ogcopenapis/OgcOpenApiFeatureStore`, the paths with `lib/` still work.
|
|
299
|
-
* New: vector tiles (OgcOpenApiVectorTilesModel), OGC API Styles (OgcOpenApiStyleTools), the tilesets of a collection
|
|
300
|
-
(`fetchCollectionTileSets`) and of the dataset (`fetchDatasetTileSets`).
|
|
301
|
-
* OgcOpenApiTilesModel uses LuciadRIA's WMTS support, create it with `createFromTileSet`. The constructor is deprecated.
|
|
302
|
-
* OgcOpenApiFeatureStore extends LuciadRIA's `Store`.
|
|
303
|
-
* `fetchTileSetsInFull` leaves out tile matrix sets whose definition cannot be read, instead of failing.
|
|
304
|
-
* Relative links are resolved against the document that has them, instead of the host of the server.
|
|
369
|
+
## Changes
|
|
370
|
+
See [CHANGELOG.md](CHANGELOG.md) for the changes of each version.
|
|
305
371
|
|
|
306
372
|
## Requirements
|
|
307
373
|
* LuciadRIA 2026.1 or higher, a peer dependency that the application installs (place it on a local npm repository,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ogcopenapis",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "OGC API Features, Maps, Tiles and Styles for LuciadRIA",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"lib/",
|
|
19
19
|
"src/",
|
|
20
20
|
"!src/**/*.test.ts",
|
|
21
|
-
"!src/fixtures/"
|
|
21
|
+
"!src/fixtures/",
|
|
22
|
+
"CHANGELOG.md"
|
|
22
23
|
],
|
|
23
24
|
"sideEffects": false,
|
|
24
25
|
"scripts": {
|