@vcmap/core 6.3.0-rc.1 → 6.3.0-rc.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/dist/cesium.d.ts +12 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/ol.d.ts +13 -2
- package/dist/src/cesium/cesium3DTileFeature.d.ts +1 -0
- package/dist/src/cesium/cesium3DTileFeature.js +16 -3
- package/dist/src/cesium/cesium3DTileFeature.js.map +1 -1
- package/dist/src/cesium/cesium3DTilePointFeature.js +2 -1
- package/dist/src/cesium/cesium3DTilePointFeature.js.map +1 -1
- package/dist/src/classRegistry.d.ts +7 -1
- package/dist/src/classRegistry.js.map +1 -1
- package/dist/src/featureProvider/abstractAttributeProvider.d.ts +62 -0
- package/dist/src/featureProvider/abstractAttributeProvider.js +129 -0
- package/dist/src/featureProvider/abstractAttributeProvider.js.map +1 -0
- package/dist/src/featureProvider/abstractFeatureProvider.d.ts +9 -18
- package/dist/src/featureProvider/abstractFeatureProvider.js +7 -38
- package/dist/src/featureProvider/abstractFeatureProvider.js.map +1 -1
- package/dist/src/featureProvider/compositeFeatureProvider.d.ts +27 -0
- package/dist/src/featureProvider/compositeFeatureProvider.js +53 -0
- package/dist/src/featureProvider/compositeFeatureProvider.js.map +1 -0
- package/dist/src/featureProvider/csvAttributeProvider.d.ts +41 -0
- package/dist/src/featureProvider/csvAttributeProvider.js +126 -0
- package/dist/src/featureProvider/csvAttributeProvider.js.map +1 -0
- package/dist/src/featureProvider/featureProviderFactory.d.ts +3 -0
- package/dist/src/featureProvider/featureProviderFactory.js +17 -0
- package/dist/src/featureProvider/featureProviderFactory.js.map +1 -0
- package/dist/src/featureProvider/i3sAttributeProvider.d.ts +7 -0
- package/dist/src/featureProvider/i3sAttributeProvider.js +43 -0
- package/dist/src/featureProvider/i3sAttributeProvider.js.map +1 -0
- package/dist/src/featureProvider/jsonAttributeProvider.d.ts +26 -0
- package/dist/src/featureProvider/jsonAttributeProvider.js +73 -0
- package/dist/src/featureProvider/jsonAttributeProvider.js.map +1 -0
- package/dist/src/featureProvider/tileProviderFeatureProvider.d.ts +4 -6
- package/dist/src/featureProvider/tileProviderFeatureProvider.js +9 -11
- package/dist/src/featureProvider/tileProviderFeatureProvider.js.map +1 -1
- package/dist/src/featureProvider/urlIdAttributeProvider.d.ts +28 -0
- package/dist/src/featureProvider/urlIdAttributeProvider.js +50 -0
- package/dist/src/featureProvider/urlIdAttributeProvider.js.map +1 -0
- package/dist/src/featureProvider/wmsFeatureProvider.d.ts +12 -3
- package/dist/src/featureProvider/wmsFeatureProvider.js +17 -6
- package/dist/src/featureProvider/wmsFeatureProvider.js.map +1 -1
- package/dist/src/interaction/featureAtPixelInteraction.d.ts +15 -3
- package/dist/src/interaction/featureAtPixelInteraction.js +41 -1
- package/dist/src/interaction/featureAtPixelInteraction.js.map +1 -1
- package/dist/src/interaction/featureProviderInteraction.js +42 -26
- package/dist/src/interaction/featureProviderInteraction.js.map +1 -1
- package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.d.ts +14 -5
- package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.js +243 -128
- package/dist/src/layer/cesium/cesiumTilesetCesiumImpl.js.map +1 -1
- package/dist/src/layer/cesium/i3sCesiumImpl.d.ts +33 -0
- package/dist/src/layer/cesium/i3sCesiumImpl.js +107 -0
- package/dist/src/layer/cesium/i3sCesiumImpl.js.map +1 -0
- package/dist/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.js +2 -1
- package/dist/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.js.map +1 -1
- package/dist/src/layer/cesium/vectorRasterTileCesiumImpl.js +7 -6
- package/dist/src/layer/cesium/vectorRasterTileCesiumImpl.js.map +1 -1
- package/dist/src/layer/cesium/vectorTileImageryProvider.js +2 -2
- package/dist/src/layer/cesium/vectorTileImageryProvider.js.map +1 -1
- package/dist/src/layer/cesiumTilesetLayer.d.ts +9 -0
- package/dist/src/layer/cesiumTilesetLayer.js +26 -1
- package/dist/src/layer/cesiumTilesetLayer.js.map +1 -1
- package/dist/src/layer/i3sLayer.d.ts +80 -0
- package/dist/src/layer/i3sLayer.js +242 -0
- package/dist/src/layer/i3sLayer.js.map +1 -0
- package/dist/src/layer/layer.d.ts +8 -3
- package/dist/src/layer/layer.js +7 -1
- package/dist/src/layer/layer.js.map +1 -1
- package/dist/src/layer/layerSymbols.d.ts +4 -0
- package/dist/src/layer/layerSymbols.js +4 -0
- package/dist/src/layer/layerSymbols.js.map +1 -1
- package/dist/src/layer/panoramaDatasetLayer.d.ts +2 -0
- package/dist/src/layer/panoramaDatasetLayer.js +33 -13
- package/dist/src/layer/panoramaDatasetLayer.js.map +1 -1
- package/dist/src/layer/tileProvider/flatGeobufTileProvider.js +3 -2
- package/dist/src/layer/tileProvider/flatGeobufTileProvider.js.map +1 -1
- package/dist/src/layer/tileProvider/mvtTileProvider.js +3 -2
- package/dist/src/layer/tileProvider/mvtTileProvider.js.map +1 -1
- package/dist/src/layer/tileProvider/tileProvider.d.ts +6 -0
- package/dist/src/layer/tileProvider/tileProvider.js +12 -1
- package/dist/src/layer/tileProvider/tileProvider.js.map +1 -1
- package/dist/src/layer/vectorLayer.js +2 -2
- package/dist/src/layer/vectorLayer.js.map +1 -1
- package/dist/src/layer/vectorProperties.js +10 -1
- package/dist/src/layer/vectorProperties.js.map +1 -1
- package/dist/src/layer/vectorTileLayer.d.ts +14 -5
- package/dist/src/layer/vectorTileLayer.js +78 -26
- package/dist/src/layer/vectorTileLayer.js.map +1 -1
- package/dist/src/layer/wmsLayer.d.ts +3 -0
- package/dist/src/layer/wmsLayer.js +62 -32
- package/dist/src/layer/wmsLayer.js.map +1 -1
- package/dist/src/map/baseCesiumMap.d.ts +4 -4
- package/dist/src/map/baseCesiumMap.js +12 -0
- package/dist/src/map/baseCesiumMap.js.map +1 -1
- package/dist/src/map/cesiumMap.js +0 -11
- package/dist/src/map/cesiumMap.js.map +1 -1
- package/dist/src/map/obliqueMap.js +11 -4
- package/dist/src/map/obliqueMap.js.map +1 -1
- package/dist/src/map/panoramaMap.js +1 -1
- package/dist/src/panorama/panoramaImage.js +6 -5
- package/dist/src/panorama/panoramaImage.js.map +1 -1
- package/dist/src/style/declarativeStyleItem.js +7 -8
- package/dist/src/style/declarativeStyleItem.js.map +1 -1
- package/dist/src/util/fetch.d.ts +7 -0
- package/dist/src/util/fetch.js +7 -0
- package/dist/src/util/fetch.js.map +1 -1
- package/dist/src/vcsApp.d.ts +2 -3
- package/dist/src/vcsApp.js.map +1 -1
- package/dist/src/vcsModuleHelpers.d.ts +5 -2
- package/dist/src/vcsModuleHelpers.js +27 -1
- package/dist/src/vcsModuleHelpers.js.map +1 -1
- package/dist/tests/unit/helpers/cesiumHelpers.js +7 -1
- package/dist/tests/unit/helpers/cesiumHelpers.js.map +1 -1
- package/index.ts +27 -0
- package/package.json +2 -2
- package/src/cesium/cesium.d.ts +12 -0
- package/src/cesium/cesium3DTileFeature.ts +25 -3
- package/src/cesium/cesium3DTilePointFeature.ts +3 -1
- package/src/classRegistry.ts +8 -3
- package/src/featureProvider/abstractAttributeProvider.ts +201 -0
- package/src/featureProvider/abstractFeatureProvider.ts +27 -47
- package/src/featureProvider/compositeFeatureProvider.ts +103 -0
- package/src/featureProvider/csvAttributeProvider.ts +186 -0
- package/src/featureProvider/featureProviderFactory.ts +31 -0
- package/src/featureProvider/i3sAttributeProvider.ts +60 -0
- package/src/featureProvider/jsonAttributeProvider.ts +109 -0
- package/src/featureProvider/tileProviderFeatureProvider.ts +13 -14
- package/src/featureProvider/urlIdAttributeProvider.ts +82 -0
- package/src/featureProvider/wmsFeatureProvider.ts +24 -7
- package/src/global.d.ts +2 -0
- package/src/interaction/featureAtPixelInteraction.ts +53 -3
- package/src/interaction/featureProviderInteraction.ts +59 -38
- package/src/layer/cesium/cesiumTilesetCesiumImpl.ts +296 -157
- package/src/layer/cesium/i3sCesiumImpl.ts +141 -0
- package/src/layer/cesium/vcsTile/vcsQuadtreeTileProvider.ts +4 -3
- package/src/layer/cesium/vectorRasterTileCesiumImpl.ts +7 -6
- package/src/layer/cesium/vectorTileImageryProvider.ts +2 -2
- package/src/layer/cesiumTilesetLayer.ts +51 -1
- package/src/layer/i3sLayer.ts +343 -0
- package/src/layer/layer.ts +30 -3
- package/src/layer/layerSymbols.ts +5 -0
- package/src/layer/panoramaDatasetLayer.ts +44 -13
- package/src/layer/tileProvider/flatGeobufTileProvider.ts +3 -2
- package/src/layer/tileProvider/mvtTileProvider.ts +3 -2
- package/src/layer/tileProvider/tileProvider.ts +13 -1
- package/src/layer/vectorLayer.ts +4 -2
- package/src/layer/vectorProperties.ts +10 -1
- package/src/layer/vectorTileLayer.ts +135 -47
- package/src/layer/wmsLayer.ts +77 -44
- package/src/map/baseCesiumMap.ts +29 -5
- package/src/map/cesiumMap.ts +0 -15
- package/src/map/obliqueMap.ts +13 -6
- package/src/map/panoramaMap.ts +1 -1
- package/src/ol/ol.d.ts +13 -2
- package/src/panorama/panoramaImage.ts +8 -5
- package/src/style/declarativeStyleItem.ts +7 -9
- package/src/util/fetch.ts +7 -0
- package/src/vcsApp.ts +7 -8
- package/src/vcsModuleHelpers.ts +62 -4
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
-
import { parseBoolean } from '@vcsuite/parsers';
|
|
3
2
|
import type { Feature } from 'ol/index.js';
|
|
4
3
|
import type { Coordinate } from 'ol/coordinate.js';
|
|
5
4
|
|
|
6
5
|
import { vcsLayerName } from '../layer/layerSymbols.js';
|
|
7
6
|
import VcsObject, { type VcsObjectOptions } from '../vcsObject.js';
|
|
8
7
|
import { getStyleOrDefaultStyle } from '../style/styleFactory.js';
|
|
9
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
defaultVectorStyle,
|
|
10
|
+
type VectorStyleItemOptions,
|
|
11
|
+
} from '../style/vectorStyleItem.js';
|
|
10
12
|
import VectorProperties, {
|
|
11
13
|
type VectorPropertiesOptions,
|
|
12
14
|
} from '../layer/vectorProperties.js';
|
|
@@ -14,20 +16,22 @@ import { isProvidedFeature } from './featureProviderSymbols.js';
|
|
|
14
16
|
import type StyleItem from '../style/styleItem.js';
|
|
15
17
|
import { type StyleItemOptions } from '../style/styleItem.js';
|
|
16
18
|
import type VcsMap from '../map/vcsMap.js';
|
|
19
|
+
import type { DeclarativeStyleItemOptions } from '../style/declarativeStyleItem.js';
|
|
20
|
+
import type Layer from '../layer/layer.js';
|
|
17
21
|
|
|
18
22
|
export type AbstractFeatureProviderOptions = VcsObjectOptions & {
|
|
19
23
|
/**
|
|
20
24
|
* the style to apply to features created by this feature provider
|
|
21
25
|
*/
|
|
22
|
-
style?:
|
|
26
|
+
style?:
|
|
27
|
+
| StyleItemOptions
|
|
28
|
+
| VectorStyleItemOptions
|
|
29
|
+
| DeclarativeStyleItemOptions
|
|
30
|
+
| StyleItem;
|
|
23
31
|
/**
|
|
24
32
|
* the vector properties of the features. Allow picking is false by default.
|
|
25
33
|
*/
|
|
26
34
|
vectorProperties?: VectorProperties | VectorPropertiesOptions;
|
|
27
|
-
/**
|
|
28
|
-
* show the resulting geometry in the map
|
|
29
|
-
*/
|
|
30
|
-
showGeometry?: boolean;
|
|
31
35
|
/**
|
|
32
36
|
* can be used to constrict the featureProvider to specific mapTypes empty array means no restriction
|
|
33
37
|
*/
|
|
@@ -38,7 +42,7 @@ export type AbstractFeatureProviderOptions = VcsObjectOptions & {
|
|
|
38
42
|
* An abstract class providing features for {@link Layer}s which cannot provide features directly, but can provide features for
|
|
39
43
|
* a given location, e.g. WmsLayer with a getFeatureInfo configuration. In this case, a feature provider can be created for this layer.
|
|
40
44
|
*/
|
|
41
|
-
class AbstractFeatureProvider extends VcsObject {
|
|
45
|
+
abstract class AbstractFeatureProvider extends VcsObject {
|
|
42
46
|
static get className(): string {
|
|
43
47
|
return 'AbstractFeatureProvider';
|
|
44
48
|
}
|
|
@@ -48,26 +52,15 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
48
52
|
vectorProperties: {
|
|
49
53
|
allowPicking: false,
|
|
50
54
|
},
|
|
51
|
-
showGeometry: false,
|
|
52
55
|
mapTypes: [],
|
|
53
56
|
};
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
/**
|
|
57
|
-
* The layer name of the associated layer
|
|
58
|
-
*/
|
|
59
|
-
layerName: string;
|
|
60
|
-
|
|
61
59
|
/**
|
|
62
60
|
* The style set on features created by this provider
|
|
63
61
|
*/
|
|
64
62
|
style: StyleItem | undefined;
|
|
65
63
|
|
|
66
|
-
/**
|
|
67
|
-
* Whether to show the geometry on selection.
|
|
68
|
-
*/
|
|
69
|
-
showGeometry: boolean;
|
|
70
|
-
|
|
71
64
|
/**
|
|
72
65
|
* The vector properties assigned to features created by this provider
|
|
73
66
|
*/
|
|
@@ -78,21 +71,14 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
78
71
|
*/
|
|
79
72
|
mapTypes: string[];
|
|
80
73
|
|
|
81
|
-
constructor(
|
|
74
|
+
constructor(options: AbstractFeatureProviderOptions) {
|
|
82
75
|
const defaultOptions = AbstractFeatureProvider.getDefaultOptions();
|
|
83
76
|
super({ ...defaultOptions, ...options });
|
|
84
77
|
|
|
85
|
-
this.layerName = layerName;
|
|
86
|
-
|
|
87
78
|
this.style = options.style
|
|
88
79
|
? getStyleOrDefaultStyle(options.style, defaultVectorStyle.clone())
|
|
89
80
|
: undefined;
|
|
90
81
|
|
|
91
|
-
this.showGeometry = parseBoolean(
|
|
92
|
-
options.showGeometry,
|
|
93
|
-
defaultOptions.showGeometry,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
82
|
this.vectorProperties =
|
|
97
83
|
options.vectorProperties instanceof VectorProperties
|
|
98
84
|
? options.vectorProperties
|
|
@@ -120,14 +106,14 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
120
106
|
* Ensures the feature has an ID, applies all vectorProperties and adds style and the vcsLayerName
|
|
121
107
|
* and isProvidedFeature symbols to the feature
|
|
122
108
|
*/
|
|
123
|
-
getProviderFeature(feature: Feature): Feature {
|
|
109
|
+
getProviderFeature(feature: Feature, layer: Layer): Feature {
|
|
124
110
|
if (!feature.getId()) {
|
|
125
111
|
feature.setId(uuidv4());
|
|
126
112
|
}
|
|
127
113
|
if (this.style) {
|
|
128
114
|
feature.setStyle(this.style.style);
|
|
129
115
|
}
|
|
130
|
-
feature[vcsLayerName] =
|
|
116
|
+
feature[vcsLayerName] = layer.name;
|
|
131
117
|
feature[isProvidedFeature] = true;
|
|
132
118
|
Object.entries(this.vectorProperties.getValues()).forEach(
|
|
133
119
|
([key, value]) => {
|
|
@@ -146,19 +132,13 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
146
132
|
* to handle your feature is called: (e.g. <code>return features.map(f => this.getProviderFeature(f)</code>);
|
|
147
133
|
* @param coordinate - in mercator
|
|
148
134
|
* @param resolution - meters per pixel for the given location
|
|
149
|
-
* @param
|
|
135
|
+
* @param layer - the layer to request the features for
|
|
150
136
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
_resolution: number,
|
|
157
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
158
|
-
_headers?: Record<string, string>,
|
|
159
|
-
): Promise<Feature[]> {
|
|
160
|
-
return Promise.resolve([]);
|
|
161
|
-
}
|
|
137
|
+
abstract getFeaturesByCoordinate(
|
|
138
|
+
coordinate: Coordinate,
|
|
139
|
+
resolution: number,
|
|
140
|
+
layer: Layer,
|
|
141
|
+
): Promise<Feature[]>;
|
|
162
142
|
|
|
163
143
|
/**
|
|
164
144
|
* Returns the object required to configure this feature provider.
|
|
@@ -168,12 +148,6 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
168
148
|
): AbstractFeatureProviderOptions {
|
|
169
149
|
const config: AbstractFeatureProviderOptions = super.toJSON(defaultOptions);
|
|
170
150
|
|
|
171
|
-
delete config.name; // the name is irrelevant, since its the layers name
|
|
172
|
-
|
|
173
|
-
if (this.showGeometry !== defaultOptions.showGeometry) {
|
|
174
|
-
config.showGeometry = this.showGeometry;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
151
|
if (this.style) {
|
|
178
152
|
config.style = this.style.toJSON();
|
|
179
153
|
}
|
|
@@ -182,9 +156,15 @@ class AbstractFeatureProvider extends VcsObject {
|
|
|
182
156
|
...VectorProperties.getDefaultOptions(),
|
|
183
157
|
...(defaultOptions.vectorProperties as VectorPropertiesOptions),
|
|
184
158
|
});
|
|
159
|
+
|
|
185
160
|
if (Object.keys(vectorPropertiesConfig).length > 0) {
|
|
186
161
|
config.vectorProperties = vectorPropertiesConfig;
|
|
187
162
|
}
|
|
163
|
+
|
|
164
|
+
if (this.mapTypes.length > 0) {
|
|
165
|
+
config.mapTypes = this.mapTypes.slice();
|
|
166
|
+
}
|
|
167
|
+
|
|
188
168
|
return config;
|
|
189
169
|
}
|
|
190
170
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type Feature from 'ol/Feature.js';
|
|
2
|
+
import type { Extent } from 'ol/extent.js';
|
|
3
|
+
import type { AbstractFeatureProviderOptions } from './abstractFeatureProvider.js';
|
|
4
|
+
import AbstractFeatureProvider from './abstractFeatureProvider.js';
|
|
5
|
+
import AbstractAttributeProvider, {
|
|
6
|
+
type AbstractAttributeProviderOptions,
|
|
7
|
+
type AttributeProvider,
|
|
8
|
+
} from './abstractAttributeProvider.js';
|
|
9
|
+
import type { EventFeature } from '../interaction/abstractInteraction.js';
|
|
10
|
+
import type Layer from '../layer/layer.js';
|
|
11
|
+
import { getProviderForOption } from './featureProviderFactory.js';
|
|
12
|
+
|
|
13
|
+
export type CompositeFeatureProviderOptions = AbstractFeatureProviderOptions & {
|
|
14
|
+
featureProviders: (
|
|
15
|
+
| AbstractFeatureProviderOptions
|
|
16
|
+
| AbstractFeatureProvider
|
|
17
|
+
)[];
|
|
18
|
+
attributeProviders: (
|
|
19
|
+
| AbstractAttributeProviderOptions
|
|
20
|
+
| AbstractAttributeProvider
|
|
21
|
+
)[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A feature provider that combines multiple feature providers and attribute providers.
|
|
26
|
+
* Used to combine multiple feature & attribute providers for a layer.
|
|
27
|
+
* The order of providers is important, as attributes are applied and
|
|
28
|
+
* features are returned in the order.
|
|
29
|
+
*/
|
|
30
|
+
export default class CompositeFeatureProvider
|
|
31
|
+
extends AbstractFeatureProvider
|
|
32
|
+
implements AttributeProvider
|
|
33
|
+
{
|
|
34
|
+
static get className(): string {
|
|
35
|
+
return 'CompositeFeatureProvider';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private _attributeProviders: AttributeProvider[];
|
|
39
|
+
|
|
40
|
+
private _featureProviders: AbstractFeatureProvider[];
|
|
41
|
+
|
|
42
|
+
constructor(options: CompositeFeatureProviderOptions) {
|
|
43
|
+
super(options);
|
|
44
|
+
this._featureProviders = options.featureProviders
|
|
45
|
+
.map(getProviderForOption)
|
|
46
|
+
.filter((fp) => fp instanceof AbstractFeatureProvider);
|
|
47
|
+
|
|
48
|
+
this._featureProviders.forEach((fp) => {
|
|
49
|
+
fp.mapTypes = this.mapTypes;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this._attributeProviders = options.attributeProviders
|
|
53
|
+
.map(getProviderForOption)
|
|
54
|
+
.filter((ap) => ap instanceof AbstractAttributeProvider);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async augmentFeatures(
|
|
58
|
+
features: EventFeature[],
|
|
59
|
+
extent?: Extent,
|
|
60
|
+
): Promise<void> {
|
|
61
|
+
for (const provider of this._attributeProviders) {
|
|
62
|
+
// order is relevant. second provider can overwrite or use attributes of first provider.
|
|
63
|
+
// eslint-disable-next-line no-await-in-loop
|
|
64
|
+
await provider.augmentFeatures(features, extent);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async getFeaturesByCoordinate(
|
|
69
|
+
coordinate: [number, number],
|
|
70
|
+
resolution: number,
|
|
71
|
+
layer: Layer,
|
|
72
|
+
): Promise<Feature[]> {
|
|
73
|
+
const featureArray = await Promise.all(
|
|
74
|
+
this._featureProviders.map((fp) =>
|
|
75
|
+
fp.getFeaturesByCoordinate(coordinate, resolution, layer),
|
|
76
|
+
),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return featureArray.flat();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async augmentFeature(feature: EventFeature): Promise<void> {
|
|
83
|
+
for (const provider of this._attributeProviders) {
|
|
84
|
+
// order is relevant. second provider can overwrite or use attributes of first provider.
|
|
85
|
+
// eslint-disable-next-line no-await-in-loop
|
|
86
|
+
await provider.augmentFeature(feature);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
toJSON(
|
|
91
|
+
defaultOptions: AbstractFeatureProviderOptions = AbstractFeatureProvider.getDefaultOptions(),
|
|
92
|
+
): CompositeFeatureProviderOptions {
|
|
93
|
+
const config: Partial<CompositeFeatureProviderOptions> = super.toJSON(
|
|
94
|
+
defaultOptions,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
config.featureProviders = this._featureProviders.map((fp) => fp.toJSON());
|
|
98
|
+
config.attributeProviders = this._attributeProviders.map((ap) =>
|
|
99
|
+
ap.toJSON(),
|
|
100
|
+
);
|
|
101
|
+
return config as CompositeFeatureProviderOptions;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import AbstractAttributeProvider, {
|
|
2
|
+
type AbstractAttributeProviderOptions,
|
|
3
|
+
} from './abstractAttributeProvider.js';
|
|
4
|
+
import { featureProviderClassRegistry } from '../classRegistry.js';
|
|
5
|
+
import { getInitForUrl } from '../util/fetch.js';
|
|
6
|
+
|
|
7
|
+
export type CsvAttributeProviderOptions = AbstractAttributeProviderOptions & {
|
|
8
|
+
/**
|
|
9
|
+
* CSV data as a string or URL to fetch the CSV data from
|
|
10
|
+
*/
|
|
11
|
+
data: string;
|
|
12
|
+
/**
|
|
13
|
+
* Delimiter used in the CSV data (default: ",")
|
|
14
|
+
*/
|
|
15
|
+
delimiter?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Column name to use as the feature ID (default: "id")
|
|
18
|
+
*/
|
|
19
|
+
idColumn?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional array of headers, if the data does not contain a header row. If not provided, the first row of the CSV data will be used as headers.
|
|
22
|
+
*/
|
|
23
|
+
headers?: string[] | null;
|
|
24
|
+
httpHeaders?: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default class CsvAttributeProvider extends AbstractAttributeProvider {
|
|
28
|
+
static get className(): string {
|
|
29
|
+
return 'CsvAttributeProvider';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static getDefaultOptions(): Required<CsvAttributeProviderOptions> {
|
|
33
|
+
return {
|
|
34
|
+
name: '',
|
|
35
|
+
keyProperty: '',
|
|
36
|
+
properties: {},
|
|
37
|
+
type: CsvAttributeProvider.className,
|
|
38
|
+
data: '',
|
|
39
|
+
delimiter: ',',
|
|
40
|
+
idColumn: 'id',
|
|
41
|
+
headers: null,
|
|
42
|
+
httpHeaders: {},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private _urlOrData: string;
|
|
47
|
+
|
|
48
|
+
private _data?: Map<string, Record<string, unknown>>;
|
|
49
|
+
|
|
50
|
+
private _delimiter: string;
|
|
51
|
+
|
|
52
|
+
private _idColumn: string;
|
|
53
|
+
|
|
54
|
+
private _headers?: string[];
|
|
55
|
+
|
|
56
|
+
private _httpHeaders?: Record<string, string>;
|
|
57
|
+
|
|
58
|
+
private _dataLoadingPromise?: Promise<void>;
|
|
59
|
+
|
|
60
|
+
constructor(options: CsvAttributeProviderOptions) {
|
|
61
|
+
const defaultOptions = CsvAttributeProvider.getDefaultOptions();
|
|
62
|
+
super({ ...defaultOptions, ...options });
|
|
63
|
+
this._urlOrData = options.data;
|
|
64
|
+
this._delimiter = options.delimiter ?? defaultOptions.delimiter;
|
|
65
|
+
this._idColumn = options.idColumn ?? defaultOptions.idColumn;
|
|
66
|
+
|
|
67
|
+
if (Array.isArray(options.headers)) {
|
|
68
|
+
this._headers = options.headers.slice();
|
|
69
|
+
}
|
|
70
|
+
if (options.httpHeaders) {
|
|
71
|
+
this._httpHeaders = structuredClone(options.httpHeaders);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private _readLine(line: string): string[] {
|
|
76
|
+
return line.split(this._delimiter).map((v) => v.trim());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private async _loadData(): Promise<void> {
|
|
80
|
+
if (this._data) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let csvData: string;
|
|
85
|
+
// Check if URL contains newline - if so, it's the data itself
|
|
86
|
+
if (this._urlOrData.includes('\n')) {
|
|
87
|
+
csvData = this._urlOrData;
|
|
88
|
+
} else {
|
|
89
|
+
const init = getInitForUrl(this._urlOrData, this._httpHeaders);
|
|
90
|
+
const response = await fetch(this._urlOrData, init);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`Failed to fetch CSV data from ${this._urlOrData}`);
|
|
93
|
+
}
|
|
94
|
+
csvData = await response.text();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Split by both Windows (\r\n) and Unix (\n) line endings
|
|
98
|
+
const lines = csvData.split(/\r?\n/).filter((line) => line.trim() !== '');
|
|
99
|
+
if (lines.length === 0) {
|
|
100
|
+
this.getLogger().warning('No CSV data available to load.');
|
|
101
|
+
this._data = new Map<string, Record<string, unknown>>();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const dataMap = new Map<string, Record<string, unknown>>();
|
|
106
|
+
|
|
107
|
+
let startIndex = 0;
|
|
108
|
+
|
|
109
|
+
if (!this._headers) {
|
|
110
|
+
this._headers = this._readLine(lines[0]);
|
|
111
|
+
startIndex = 1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
115
|
+
const values = this._readLine(lines[i]);
|
|
116
|
+
|
|
117
|
+
const attributes: Record<string, unknown> = {};
|
|
118
|
+
|
|
119
|
+
for (let j = 0; j < values.length; j++) {
|
|
120
|
+
const key = this._headers[j] ?? `column_${j}`;
|
|
121
|
+
attributes[key] = values[j];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const id = attributes[this._idColumn];
|
|
125
|
+
if (typeof id === 'string') {
|
|
126
|
+
dataMap.set(id, attributes);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this._data = dataMap;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private _ensureDataLoaded(): Promise<void> {
|
|
134
|
+
if (!this._dataLoadingPromise) {
|
|
135
|
+
this._dataLoadingPromise = this._loadData();
|
|
136
|
+
}
|
|
137
|
+
return this._dataLoadingPromise;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
protected async _getAttributes(
|
|
141
|
+
key: string,
|
|
142
|
+
): Promise<Record<string, unknown> | undefined> {
|
|
143
|
+
await this._ensureDataLoaded();
|
|
144
|
+
return this._data?.get(key);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
protected async _getBulkAttributes(
|
|
148
|
+
bulk: {
|
|
149
|
+
key: string;
|
|
150
|
+
}[],
|
|
151
|
+
): Promise<(Record<string, unknown> | undefined)[]> {
|
|
152
|
+
await this._ensureDataLoaded();
|
|
153
|
+
return bulk.map(({ key }) => this._data?.get(key));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
toJSON(
|
|
157
|
+
defaultOptions = CsvAttributeProvider.getDefaultOptions(),
|
|
158
|
+
): CsvAttributeProviderOptions {
|
|
159
|
+
const config = super.toJSON(defaultOptions) as CsvAttributeProviderOptions;
|
|
160
|
+
config.data = this._urlOrData;
|
|
161
|
+
if (this._delimiter !== defaultOptions.delimiter) {
|
|
162
|
+
config.delimiter = this._delimiter;
|
|
163
|
+
}
|
|
164
|
+
if (this._idColumn !== defaultOptions.idColumn) {
|
|
165
|
+
config.idColumn = this._idColumn;
|
|
166
|
+
}
|
|
167
|
+
if (this._headers && this._headers.length > 0) {
|
|
168
|
+
config.headers = this._headers.slice();
|
|
169
|
+
}
|
|
170
|
+
if (this._httpHeaders) {
|
|
171
|
+
config.httpHeaders = structuredClone(this._httpHeaders);
|
|
172
|
+
}
|
|
173
|
+
return config;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
destroy(): void {
|
|
177
|
+
this._data?.clear();
|
|
178
|
+
this._data = undefined;
|
|
179
|
+
super.destroy();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
featureProviderClassRegistry.registerClass(
|
|
184
|
+
CsvAttributeProvider.className,
|
|
185
|
+
CsvAttributeProvider,
|
|
186
|
+
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import AbstractFeatureProvider, {
|
|
2
|
+
type AbstractFeatureProviderOptions,
|
|
3
|
+
} from './abstractFeatureProvider.js';
|
|
4
|
+
import AbstractAttributeProvider, {
|
|
5
|
+
type AbstractAttributeProviderOptions,
|
|
6
|
+
} from './abstractAttributeProvider.js';
|
|
7
|
+
import { featureProviderClassRegistry } from '../classRegistry.js';
|
|
8
|
+
|
|
9
|
+
export function getProviderForOption(
|
|
10
|
+
options?:
|
|
11
|
+
| AbstractFeatureProviderOptions
|
|
12
|
+
| AbstractAttributeProviderOptions
|
|
13
|
+
| AbstractAttributeProvider
|
|
14
|
+
| AbstractFeatureProvider,
|
|
15
|
+
): AbstractFeatureProvider | AbstractAttributeProvider | undefined {
|
|
16
|
+
if (
|
|
17
|
+
options instanceof AbstractFeatureProvider ||
|
|
18
|
+
options instanceof AbstractAttributeProvider
|
|
19
|
+
) {
|
|
20
|
+
return options;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (options?.type) {
|
|
24
|
+
const CTOR = featureProviderClassRegistry.getClass(options.type);
|
|
25
|
+
if (CTOR) {
|
|
26
|
+
return new CTOR(options);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { getLogger } from '@vcsuite/logger';
|
|
2
|
+
import type { I3SNode } from '@vcmap-cesium/engine';
|
|
3
|
+
import { Cesium3DTileFeature } from '@vcmap-cesium/engine';
|
|
4
|
+
import Feature from 'ol/Feature.js';
|
|
5
|
+
import { isI3SFeature } from '../interaction/featureAtPixelInteraction.js';
|
|
6
|
+
import AbstractAttributeProvider from './abstractAttributeProvider.js';
|
|
7
|
+
import { isProvidedFeature } from './featureProviderSymbols.js';
|
|
8
|
+
import { i3sData } from '../layer/layerSymbols.js';
|
|
9
|
+
|
|
10
|
+
export default class I3SAttributeProvider extends AbstractAttributeProvider {
|
|
11
|
+
static get className(): string {
|
|
12
|
+
return 'I3SAttributeProvider';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
protected async _getAttributes(
|
|
16
|
+
_key: string,
|
|
17
|
+
feature: Cesium3DTileFeature | Feature,
|
|
18
|
+
): Promise<Record<string, unknown> | undefined> {
|
|
19
|
+
if (feature instanceof Cesium3DTileFeature) {
|
|
20
|
+
const id = feature.featureId;
|
|
21
|
+
|
|
22
|
+
if (id && feature.content?.tile?.i3sNode) {
|
|
23
|
+
const node = feature.content.tile.i3sNode as unknown as I3SNode;
|
|
24
|
+
return node
|
|
25
|
+
.loadFields()
|
|
26
|
+
.then(() => node.getFieldsForFeature(id) as Record<string, unknown>)
|
|
27
|
+
.catch(() => {
|
|
28
|
+
getLogger(this.className).warning(
|
|
29
|
+
`Error getting I3S fields for feature with id ${id}`,
|
|
30
|
+
);
|
|
31
|
+
return undefined;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
} else if (
|
|
35
|
+
feature instanceof Feature &&
|
|
36
|
+
feature[isProvidedFeature] &&
|
|
37
|
+
isI3SFeature(feature)
|
|
38
|
+
) {
|
|
39
|
+
const { i3sNode, cartesianPosition } = feature[i3sData];
|
|
40
|
+
if (i3sNode && cartesianPosition) {
|
|
41
|
+
return i3sNode
|
|
42
|
+
.loadFields()
|
|
43
|
+
.then(
|
|
44
|
+
() =>
|
|
45
|
+
i3sNode.getFieldsForPickedPosition(cartesianPosition) as Record<
|
|
46
|
+
string,
|
|
47
|
+
unknown
|
|
48
|
+
>,
|
|
49
|
+
)
|
|
50
|
+
.catch(() => {
|
|
51
|
+
getLogger(this.className).warning(
|
|
52
|
+
'Error getting I3S fields for picked position',
|
|
53
|
+
);
|
|
54
|
+
return undefined;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { is, oneOf } from '@vcsuite/check';
|
|
2
|
+
import AbstractAttributeProvider, {
|
|
3
|
+
type AbstractAttributeProviderOptions,
|
|
4
|
+
} from './abstractAttributeProvider.js';
|
|
5
|
+
import { getInitForUrl, requestJson } from '../util/fetch.js';
|
|
6
|
+
|
|
7
|
+
export type JsonAttributeData = {
|
|
8
|
+
features: { id: string | number; properties: Record<string, unknown> }[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type JsonAttributeProviderOptions = AbstractAttributeProviderOptions & {
|
|
12
|
+
data: string | JsonAttributeData;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default class JsonAttributeProvider extends AbstractAttributeProvider {
|
|
17
|
+
static get className(): string {
|
|
18
|
+
return 'JsonAttributeProvider';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static getDefaultOptions(): JsonAttributeProviderOptions {
|
|
22
|
+
return {
|
|
23
|
+
...AbstractAttributeProvider.getDefaultOptions(),
|
|
24
|
+
data: '',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private _data?: Map<string, Record<string, unknown>>;
|
|
29
|
+
|
|
30
|
+
private readonly _dataOrUrl: string | JsonAttributeData;
|
|
31
|
+
|
|
32
|
+
private readonly _headers?: Record<string, string>;
|
|
33
|
+
|
|
34
|
+
constructor(options: JsonAttributeProviderOptions) {
|
|
35
|
+
super(options);
|
|
36
|
+
|
|
37
|
+
this._dataOrUrl = is(options.data, Object)
|
|
38
|
+
? structuredClone(options.data)
|
|
39
|
+
: options.data;
|
|
40
|
+
this._headers = options.headers;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async _loadData(): Promise<void> {
|
|
44
|
+
if (this._data) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let serializedData;
|
|
49
|
+
if (is(this._dataOrUrl, String)) {
|
|
50
|
+
const init = getInitForUrl(this._dataOrUrl, this._headers);
|
|
51
|
+
serializedData = await requestJson<JsonAttributeData>(
|
|
52
|
+
this._dataOrUrl,
|
|
53
|
+
init,
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
serializedData = this._dataOrUrl;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const data = new Map<string, Record<string, unknown>>();
|
|
60
|
+
if (Array.isArray(serializedData.features)) {
|
|
61
|
+
serializedData?.features?.forEach(({ id, properties }) => {
|
|
62
|
+
if (is(id, oneOf(String, Number)) && is(properties, Object)) {
|
|
63
|
+
data.set(String(id), properties);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this._data = data;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected async _getAttributes(
|
|
72
|
+
key: string,
|
|
73
|
+
): Promise<Record<string, unknown> | undefined> {
|
|
74
|
+
await this._loadData();
|
|
75
|
+
return this._data?.get(key);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
protected async _getBulkAttributes(
|
|
79
|
+
bulk: {
|
|
80
|
+
key: string;
|
|
81
|
+
}[],
|
|
82
|
+
): Promise<(Record<string, unknown> | undefined)[]> {
|
|
83
|
+
await this._loadData();
|
|
84
|
+
return bulk.map(({ key }) => this._data?.get(key));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
toJSON(
|
|
88
|
+
defaultOptions = JsonAttributeProvider.getDefaultOptions(),
|
|
89
|
+
): JsonAttributeProviderOptions {
|
|
90
|
+
const config = super.toJSON(defaultOptions) as JsonAttributeProviderOptions;
|
|
91
|
+
if (is(this._dataOrUrl, Object)) {
|
|
92
|
+
config.data = structuredClone(this._dataOrUrl);
|
|
93
|
+
} else {
|
|
94
|
+
config.data = this._dataOrUrl;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (this._headers) {
|
|
98
|
+
config.headers = structuredClone(this._headers);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return config;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
destroy(): void {
|
|
105
|
+
this._data?.clear();
|
|
106
|
+
this._data = undefined;
|
|
107
|
+
super.destroy();
|
|
108
|
+
}
|
|
109
|
+
}
|