@vcmap/core 6.0.7 → 6.1.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 +3 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/ol.d.ts +8 -1
- package/dist/src/featureProvider/featureProviderSymbols.d.ts +5 -0
- package/dist/src/featureProvider/featureProviderSymbols.js +5 -1
- package/dist/src/featureProvider/featureProviderSymbols.js.map +1 -1
- package/dist/src/interaction/featureAtPixelInteraction.js +58 -62
- package/dist/src/interaction/featureAtPixelInteraction.js.map +1 -1
- package/dist/src/interaction/featureProviderInteraction.js +25 -13
- package/dist/src/interaction/featureProviderInteraction.js.map +1 -1
- package/dist/src/layer/cesium/sourceVectorContextSync.d.ts +27 -0
- package/dist/src/layer/cesium/sourceVectorContextSync.js +94 -0
- package/dist/src/layer/cesium/sourceVectorContextSync.js.map +1 -0
- package/dist/src/layer/cesium/vectorCesiumImpl.d.ts +4 -27
- package/dist/src/layer/cesium/vectorCesiumImpl.js +15 -107
- package/dist/src/layer/cesium/vectorCesiumImpl.js.map +1 -1
- package/dist/src/layer/cesium/vectorContext.d.ts +12 -1
- package/dist/src/layer/cesium/vectorContext.js +6 -0
- package/dist/src/layer/cesium/vectorContext.js.map +1 -1
- package/dist/src/layer/layerSymbols.js +1 -1
- package/dist/src/layer/layerSymbols.js.map +1 -1
- package/dist/src/layer/oblique/sourceObliqueSync.d.ts +18 -0
- package/dist/src/layer/oblique/sourceObliqueSync.js +319 -0
- package/dist/src/layer/oblique/sourceObliqueSync.js.map +1 -0
- package/dist/src/layer/oblique/vectorObliqueImpl.d.ts +2 -40
- package/dist/src/layer/oblique/vectorObliqueImpl.js +8 -283
- package/dist/src/layer/oblique/vectorObliqueImpl.js.map +1 -1
- package/dist/src/layer/vectorLayer.d.ts +10 -1
- package/dist/src/layer/vectorLayer.js +23 -1
- package/dist/src/layer/vectorLayer.js.map +1 -1
- package/dist/src/map/baseOLMap.js +8 -1
- package/dist/src/map/baseOLMap.js.map +1 -1
- package/dist/src/map/cesiumMap.d.ts +2 -0
- package/dist/src/map/cesiumMap.js +26 -1
- package/dist/src/map/cesiumMap.js.map +1 -1
- package/dist/src/map/vcsMap.d.ts +24 -12
- package/dist/src/map/vcsMap.js +92 -38
- package/dist/src/map/vcsMap.js.map +1 -1
- package/dist/src/ol/source/ClusterEnhancedVectorSource.d.ts +6 -4
- package/dist/src/ol/source/ClusterEnhancedVectorSource.js +4 -9
- package/dist/src/ol/source/ClusterEnhancedVectorSource.js.map +1 -1
- package/dist/src/ol/source/VcsCluster.d.ts +10 -10
- package/dist/src/ol/source/VcsCluster.js +23 -7
- package/dist/src/ol/source/VcsCluster.js.map +1 -1
- package/dist/src/util/clipping/clippingPolygonHelper.d.ts +7 -0
- package/dist/src/util/clipping/clippingPolygonHelper.js +53 -0
- package/dist/src/util/clipping/clippingPolygonHelper.js.map +1 -0
- package/dist/src/util/clipping/clippingPolygonObject.d.ts +59 -0
- package/dist/src/util/clipping/clippingPolygonObject.js +158 -0
- package/dist/src/util/clipping/clippingPolygonObject.js.map +1 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.d.ts +18 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.js +167 -0
- package/dist/src/util/clipping/clippingPolygonObjectCollection.js.map +1 -0
- package/dist/src/util/layerCollection.d.ts +11 -1
- package/dist/src/util/layerCollection.js +67 -12
- package/dist/src/util/layerCollection.js.map +1 -1
- package/dist/src/util/mapCollection.d.ts +16 -1
- package/dist/src/util/mapCollection.js +37 -3
- package/dist/src/util/mapCollection.js.map +1 -1
- package/dist/src/util/renderScreenshot.d.ts +9 -0
- package/dist/src/util/renderScreenshot.js +162 -0
- package/dist/src/util/renderScreenshot.js.map +1 -0
- package/dist/src/util/rotation.d.ts +30 -0
- package/dist/src/util/rotation.js +145 -0
- package/dist/src/util/rotation.js.map +1 -0
- package/dist/src/util/vcsTemplate.d.ts +7 -0
- package/dist/src/util/vcsTemplate.js +248 -0
- package/dist/src/util/vcsTemplate.js.map +1 -0
- package/dist/src/vcsApp.d.ts +7 -0
- package/dist/src/vcsApp.js +29 -0
- package/dist/src/vcsApp.js.map +1 -1
- package/dist/src/vcsModule.d.ts +6 -2
- package/dist/src/vcsModule.js.map +1 -1
- package/dist/src/vectorCluster/vectorClusterCesiumContext.d.ts +18 -0
- package/dist/src/{layer/cesium/clusterContext.js → vectorCluster/vectorClusterCesiumContext.js} +28 -42
- package/dist/src/vectorCluster/vectorClusterCesiumContext.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroup.d.ts +96 -0
- package/dist/src/vectorCluster/vectorClusterGroup.js +320 -0
- package/dist/src/vectorCluster/vectorClusterGroup.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.d.ts +20 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js +115 -0
- package/dist/src/vectorCluster/vectorClusterGroupCesiumImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.d.ts +19 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.js +37 -0
- package/dist/src/vectorCluster/vectorClusterGroupCollection.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.d.ts +31 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.js +76 -0
- package/dist/src/vectorCluster/vectorClusterGroupImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.d.ts +17 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js +62 -0
- package/dist/src/vectorCluster/vectorClusterGroupObliqueImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.d.ts +17 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js +62 -0
- package/dist/src/vectorCluster/vectorClusterGroupOpenlayersImpl.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.d.ts +110 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.js +374 -0
- package/dist/src/vectorCluster/vectorClusterStyleItem.js.map +1 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.d.ts +1 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.js +3 -0
- package/dist/src/vectorCluster/vectorClusterSymbols.js.map +1 -0
- package/index.ts +42 -1
- package/package.json +3 -1
- package/src/cesium/cesium.d.ts +3 -0
- package/src/featureProvider/featureProviderSymbols.ts +6 -1
- package/src/interaction/featureAtPixelInteraction.ts +109 -84
- package/src/interaction/featureProviderInteraction.ts +42 -28
- package/src/layer/cesium/sourceVectorContextSync.ts +134 -0
- package/src/layer/cesium/vcsTile/vcsDebugTile.ts +1 -1
- package/src/layer/cesium/vcsTile/vcsVectorTile.ts +1 -1
- package/src/layer/cesium/vectorCesiumImpl.ts +30 -144
- package/src/layer/cesium/vectorContext.ts +17 -1
- package/src/layer/layerSymbols.ts +1 -1
- package/src/layer/oblique/sourceObliqueSync.ts +436 -0
- package/src/layer/oblique/vectorObliqueImpl.ts +11 -397
- package/src/layer/vectorLayer.ts +35 -2
- package/src/map/baseOLMap.ts +8 -1
- package/src/map/cesiumMap.ts +36 -3
- package/src/map/vcsMap.ts +121 -47
- package/src/ol/ol.d.ts +8 -1
- package/src/ol/source/{ClusterEnhancedVectorSource.js → ClusterEnhancedVectorSource.ts} +7 -10
- package/src/ol/source/VcsCluster.ts +58 -0
- package/src/util/clipping/clippingPolygonHelper.ts +86 -0
- package/src/util/clipping/clippingPolygonObject.ts +223 -0
- package/src/util/clipping/clippingPolygonObjectCollection.ts +249 -0
- package/src/util/layerCollection.ts +90 -12
- package/src/util/mapCollection.ts +53 -2
- package/src/util/renderScreenshot.ts +193 -0
- package/src/util/rotation.ts +215 -0
- package/src/util/vcsTemplate.ts +373 -0
- package/src/vcsApp.ts +65 -0
- package/src/vcsModule.ts +6 -2
- package/src/vectorCluster/vectorClusterCesiumContext.ts +123 -0
- package/src/vectorCluster/vectorClusterGroup.ts +463 -0
- package/src/vectorCluster/vectorClusterGroupCesiumImpl.ts +176 -0
- package/src/vectorCluster/vectorClusterGroupCollection.ts +43 -0
- package/src/vectorCluster/vectorClusterGroupImpl.ts +107 -0
- package/src/vectorCluster/vectorClusterGroupObliqueImpl.ts +84 -0
- package/src/vectorCluster/vectorClusterGroupOpenlayersImpl.ts +81 -0
- package/src/vectorCluster/vectorClusterStyleItem.ts +490 -0
- package/src/vectorCluster/vectorClusterSymbols.ts +2 -0
- package/dist/src/layer/cesium/clusterContext.d.ts +0 -20
- package/dist/src/layer/cesium/clusterContext.js.map +0 -1
- package/src/layer/cesium/clusterContext.ts +0 -140
- package/src/ol/source/VcsCluster.js +0 -37
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { getLogger } from '@vcsuite/logger';
|
|
2
|
+
import VectorSource from 'ol/source/Vector.js';
|
|
3
|
+
import { unByKey } from 'ol/Observable.js';
|
|
4
|
+
import { Feature } from 'ol';
|
|
5
|
+
import { Extent as OLExtent } from 'ol/extent.js';
|
|
6
|
+
import type { Geometry } from 'ol/geom.js';
|
|
7
|
+
import type { EventsKey } from 'ol/events.js';
|
|
8
|
+
import ObliqueMap from '../../map/obliqueMap.js';
|
|
9
|
+
import {
|
|
10
|
+
actuallyIsCircle,
|
|
11
|
+
alreadyTransformedToImage,
|
|
12
|
+
doNotTransform,
|
|
13
|
+
obliqueGeometry,
|
|
14
|
+
originalFeatureSymbol,
|
|
15
|
+
} from '../vectorSymbols.js';
|
|
16
|
+
import {
|
|
17
|
+
getPolygonizedGeometry,
|
|
18
|
+
imageGeometryToMercatorGeometry,
|
|
19
|
+
mercatorGeometryToImageGeometry,
|
|
20
|
+
setNewGeometry,
|
|
21
|
+
} from './obliqueHelpers.js';
|
|
22
|
+
import type ObliqueImage from '../../oblique/obliqueImage.js';
|
|
23
|
+
import { mercatorProjection } from '../../util/projection.js';
|
|
24
|
+
|
|
25
|
+
export type SourceObliqueSync = {
|
|
26
|
+
readonly active: boolean;
|
|
27
|
+
readonly obliqueSource: VectorSource;
|
|
28
|
+
activate(): void;
|
|
29
|
+
deactivate(): void;
|
|
30
|
+
destroy(): void;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type UpdatingTimeouts = Record<
|
|
34
|
+
string | number,
|
|
35
|
+
number | boolean | null | NodeJS.Timeout
|
|
36
|
+
>;
|
|
37
|
+
|
|
38
|
+
type FeatureListeners = {
|
|
39
|
+
originalFeatureGeometryChanged: EventsKey;
|
|
40
|
+
originalFeatureChanged: EventsKey;
|
|
41
|
+
originalGeometryChanged: EventsKey;
|
|
42
|
+
obliqueGeometryChanged: EventsKey;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function featureInExtent(feature: Feature, extent?: OLExtent): boolean {
|
|
46
|
+
if (extent) {
|
|
47
|
+
const geometry = feature.getGeometry();
|
|
48
|
+
if (geometry) {
|
|
49
|
+
return (
|
|
50
|
+
geometry[alreadyTransformedToImage] || geometry.intersectsExtent(extent)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function createFeatureListener(
|
|
58
|
+
originalFeature: Feature,
|
|
59
|
+
obliqueFeature: Feature,
|
|
60
|
+
updatingMercator: UpdatingTimeouts,
|
|
61
|
+
updateObliqueGeometry: (
|
|
62
|
+
originalFeature: Feature,
|
|
63
|
+
obliqueFeature: Feature,
|
|
64
|
+
) => void,
|
|
65
|
+
updateMercatorGeometry: (
|
|
66
|
+
originalFeature: Feature,
|
|
67
|
+
obliqueFeature: Feature,
|
|
68
|
+
) => void,
|
|
69
|
+
): () => void {
|
|
70
|
+
const featureId = obliqueFeature.getId() as string | number;
|
|
71
|
+
|
|
72
|
+
const originalGeometryChanged = (listeners: FeatureListeners): void => {
|
|
73
|
+
unByKey(listeners.originalGeometryChanged);
|
|
74
|
+
unByKey(listeners.obliqueGeometryChanged);
|
|
75
|
+
setNewGeometry(originalFeature, obliqueFeature);
|
|
76
|
+
updateObliqueGeometry(originalFeature, obliqueFeature);
|
|
77
|
+
listeners.originalGeometryChanged = originalFeature
|
|
78
|
+
.getGeometry()!
|
|
79
|
+
.on('change', () => {
|
|
80
|
+
updateObliqueGeometry(originalFeature, obliqueFeature);
|
|
81
|
+
});
|
|
82
|
+
listeners.obliqueGeometryChanged = obliqueFeature
|
|
83
|
+
.getGeometry()!
|
|
84
|
+
.on('change', () => {
|
|
85
|
+
updateMercatorGeometry(originalFeature, obliqueFeature);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const listeners: FeatureListeners = {
|
|
90
|
+
originalFeatureGeometryChanged: originalFeature.on(
|
|
91
|
+
'change:geometry',
|
|
92
|
+
() => {
|
|
93
|
+
const originalGeometry = originalFeature.getGeometry() as Geometry;
|
|
94
|
+
if (originalGeometry[actuallyIsCircle]) {
|
|
95
|
+
unByKey(listeners.originalGeometryChanged);
|
|
96
|
+
listeners.originalGeometryChanged = originalFeature
|
|
97
|
+
.getGeometry()!
|
|
98
|
+
.on('change', () => {
|
|
99
|
+
if (updatingMercator[featureId]) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
delete originalGeometry[actuallyIsCircle];
|
|
103
|
+
originalGeometryChanged(listeners);
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
originalGeometryChanged(listeners);
|
|
108
|
+
},
|
|
109
|
+
),
|
|
110
|
+
originalFeatureChanged: originalFeature.on('change', () => {
|
|
111
|
+
obliqueFeature.setStyle(originalFeature.getStyle());
|
|
112
|
+
}),
|
|
113
|
+
originalGeometryChanged: originalFeature.getGeometry()!.on('change', () => {
|
|
114
|
+
updateObliqueGeometry(originalFeature, obliqueFeature);
|
|
115
|
+
}),
|
|
116
|
+
obliqueGeometryChanged: obliqueFeature.getGeometry()!.on('change', () => {
|
|
117
|
+
updateMercatorGeometry(originalFeature, obliqueFeature);
|
|
118
|
+
}),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return () => {
|
|
122
|
+
unByKey(Object.values(listeners));
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function clearUpdatingTimeouts(timeouts: UpdatingTimeouts): void {
|
|
127
|
+
Object.values(timeouts).forEach((timeout) => {
|
|
128
|
+
if (typeof timeout !== 'boolean') {
|
|
129
|
+
clearTimeout(timeout as number);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Creates a SourceObliqueSync. This ensures that the features in the source are synced to the oblique source.
|
|
136
|
+
* Adding, removing and changing features in the source will be reflected in the oblique source. Changing the oblique geometry will
|
|
137
|
+
* be synced back onto the original geometry. Changing the geometry will create a new oblique geometry on the same feature.
|
|
138
|
+
* Feature changes will lead to an update of style.
|
|
139
|
+
* @param source
|
|
140
|
+
* @param map
|
|
141
|
+
*/
|
|
142
|
+
export function createSourceObliqueSync(
|
|
143
|
+
source: VectorSource,
|
|
144
|
+
map: ObliqueMap,
|
|
145
|
+
): SourceObliqueSync {
|
|
146
|
+
const obliqueSource = new VectorSource();
|
|
147
|
+
let active = false;
|
|
148
|
+
let sourceListeners = (): void => {};
|
|
149
|
+
let imageChangedListener: (() => void) | undefined;
|
|
150
|
+
const featureListeners = new Map<string | number, () => void>();
|
|
151
|
+
|
|
152
|
+
let updatingMercator: UpdatingTimeouts = {};
|
|
153
|
+
let updatingOblique: UpdatingTimeouts = {};
|
|
154
|
+
|
|
155
|
+
// the extent of the current image
|
|
156
|
+
let currentExtent: OLExtent | undefined;
|
|
157
|
+
|
|
158
|
+
let currentImageName: string | undefined;
|
|
159
|
+
|
|
160
|
+
const convertToOblique = async (
|
|
161
|
+
originalFeature: Feature,
|
|
162
|
+
obliqueFeature: Feature,
|
|
163
|
+
): Promise<void> => {
|
|
164
|
+
const id = originalFeature.getId()!;
|
|
165
|
+
const vectorGeometry = originalFeature.getGeometry() as Geometry;
|
|
166
|
+
const imageGeometry = obliqueFeature.getGeometry() as Geometry;
|
|
167
|
+
updatingOblique[id] = true;
|
|
168
|
+
let promise: Promise<unknown>;
|
|
169
|
+
if (!vectorGeometry[alreadyTransformedToImage]) {
|
|
170
|
+
promise = mercatorGeometryToImageGeometry(
|
|
171
|
+
vectorGeometry,
|
|
172
|
+
imageGeometry,
|
|
173
|
+
map.currentImage as ObliqueImage,
|
|
174
|
+
);
|
|
175
|
+
} else {
|
|
176
|
+
obliqueFeature
|
|
177
|
+
.getGeometry()!
|
|
178
|
+
.setCoordinates(vectorGeometry.getCoordinates());
|
|
179
|
+
// we MUST wait for a promise, otherwise this is sync and you can add a feature twice
|
|
180
|
+
promise = Promise.resolve();
|
|
181
|
+
}
|
|
182
|
+
await promise;
|
|
183
|
+
updatingOblique[id] = null;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const updateObliqueGeometry = (
|
|
187
|
+
originalFeature: Feature,
|
|
188
|
+
obliqueFeature: Feature,
|
|
189
|
+
): void => {
|
|
190
|
+
const id = originalFeature.getId()!;
|
|
191
|
+
if (updatingMercator[id]) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (updatingOblique[id] != null) {
|
|
195
|
+
clearTimeout(updatingOblique[id] as number);
|
|
196
|
+
}
|
|
197
|
+
if (originalFeature.getGeometry()?.[alreadyTransformedToImage]) {
|
|
198
|
+
convertToOblique(originalFeature, obliqueFeature)
|
|
199
|
+
.catch((_e) => {
|
|
200
|
+
getLogger('SourceObliqueSync').warning(
|
|
201
|
+
`Failed to convert feature with id ${id} to oblique`,
|
|
202
|
+
);
|
|
203
|
+
})
|
|
204
|
+
.finally(() => {
|
|
205
|
+
updatingOblique[id] = null;
|
|
206
|
+
});
|
|
207
|
+
} else {
|
|
208
|
+
updatingOblique[id] = setTimeout(() => {
|
|
209
|
+
convertToOblique(originalFeature, obliqueFeature)
|
|
210
|
+
.catch((_e) => {
|
|
211
|
+
getLogger('SourceObliqueSync').warning(
|
|
212
|
+
`Failed to convert feature with id ${id} to oblique`,
|
|
213
|
+
);
|
|
214
|
+
})
|
|
215
|
+
.finally(() => {
|
|
216
|
+
updatingOblique[id] = null;
|
|
217
|
+
});
|
|
218
|
+
}, 200);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const updateMercatorGeometry = (
|
|
223
|
+
originalFeature: Feature,
|
|
224
|
+
obliqueFeature: Feature,
|
|
225
|
+
): void => {
|
|
226
|
+
const id = originalFeature.getId() as string | number;
|
|
227
|
+
if (updatingOblique[id]) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (updatingMercator[id] != null) {
|
|
231
|
+
clearTimeout(updatingMercator[id] as number);
|
|
232
|
+
}
|
|
233
|
+
const imageName = currentImageName;
|
|
234
|
+
updatingMercator[id] = setTimeout(() => {
|
|
235
|
+
const originalGeometry = getPolygonizedGeometry(originalFeature, false);
|
|
236
|
+
if (originalGeometry[actuallyIsCircle]) {
|
|
237
|
+
originalFeature.setGeometry(originalGeometry);
|
|
238
|
+
}
|
|
239
|
+
const imageGeometry = getPolygonizedGeometry(obliqueFeature, true);
|
|
240
|
+
updatingMercator[id] = true;
|
|
241
|
+
imageGeometryToMercatorGeometry(
|
|
242
|
+
imageGeometry,
|
|
243
|
+
originalGeometry,
|
|
244
|
+
map.collection!.getImageByName(imageName as string) as ObliqueImage,
|
|
245
|
+
)
|
|
246
|
+
.catch((_e) => {
|
|
247
|
+
getLogger('SourceObliqueSync').warning(
|
|
248
|
+
`Failed to update feature with id ${id} mercator geometry`,
|
|
249
|
+
);
|
|
250
|
+
})
|
|
251
|
+
.finally(() => {
|
|
252
|
+
updatingMercator[id] = null;
|
|
253
|
+
});
|
|
254
|
+
}, 200);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const addFeature = async (originalFeature: Feature): Promise<void> => {
|
|
258
|
+
if (!active) {
|
|
259
|
+
currentImageName = undefined;
|
|
260
|
+
} else if (currentExtent) {
|
|
261
|
+
const id = originalFeature.getId()!;
|
|
262
|
+
const originalGeometry = originalFeature.getGeometry();
|
|
263
|
+
if (originalFeature[doNotTransform]) {
|
|
264
|
+
if (originalGeometry && !obliqueSource.getFeatureById(id)) {
|
|
265
|
+
obliqueSource.addFeature(originalFeature);
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (obliqueSource.getFeatureById(id) || updatingOblique[id] != null) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const obliqueFeature = new Feature({});
|
|
274
|
+
obliqueFeature.setId(id);
|
|
275
|
+
obliqueFeature[originalFeatureSymbol] = originalFeature;
|
|
276
|
+
setNewGeometry(originalFeature, obliqueFeature);
|
|
277
|
+
obliqueFeature.setStyle(originalFeature.getStyle());
|
|
278
|
+
|
|
279
|
+
const featureListener = createFeatureListener(
|
|
280
|
+
originalFeature,
|
|
281
|
+
obliqueFeature,
|
|
282
|
+
updatingMercator,
|
|
283
|
+
updateObliqueGeometry,
|
|
284
|
+
updateMercatorGeometry,
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
await convertToOblique(originalFeature, obliqueFeature);
|
|
288
|
+
if (source.hasFeature(originalFeature)) {
|
|
289
|
+
// if not in source, feature has been removed in between.
|
|
290
|
+
obliqueSource.addFeature(obliqueFeature);
|
|
291
|
+
featureListeners.set(id, featureListener);
|
|
292
|
+
} else {
|
|
293
|
+
featureListener();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const removeFeature = (feature: Feature): void => {
|
|
299
|
+
const id = feature.getId()!;
|
|
300
|
+
const feat = obliqueSource.getFeatureById(id);
|
|
301
|
+
if (updatingOblique[id] != null) {
|
|
302
|
+
clearTimeout(updatingOblique[id] as number);
|
|
303
|
+
updatingOblique[id] = null;
|
|
304
|
+
}
|
|
305
|
+
if (feat) {
|
|
306
|
+
featureListeners.get(id)?.();
|
|
307
|
+
featureListeners.delete(id);
|
|
308
|
+
obliqueSource.removeFeature(feat);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const setSourceListeners = (): void => {
|
|
313
|
+
sourceListeners();
|
|
314
|
+
const listeners = [
|
|
315
|
+
source.on('addfeature', (event) => {
|
|
316
|
+
const f = event.feature as Feature;
|
|
317
|
+
if (featureInExtent(f, currentExtent)) {
|
|
318
|
+
addFeature(f).catch((_e) => {
|
|
319
|
+
getLogger('SourceObliqueSync').warning(
|
|
320
|
+
`Failed to add feature with id ${f.getId()!} to oblique source`,
|
|
321
|
+
);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}),
|
|
325
|
+
source.on('removefeature', (event) => {
|
|
326
|
+
removeFeature(event.feature as Feature);
|
|
327
|
+
}),
|
|
328
|
+
source.on('changefeature', (event) => {
|
|
329
|
+
const f = event.feature as Feature;
|
|
330
|
+
const newFeatureId = f.getId()!;
|
|
331
|
+
if (
|
|
332
|
+
!featureListeners.has(newFeatureId) &&
|
|
333
|
+
featureInExtent(f, currentExtent)
|
|
334
|
+
) {
|
|
335
|
+
addFeature(f).catch((_e) => {
|
|
336
|
+
getLogger('SourceObliqueSync').warning(
|
|
337
|
+
`Failed to add feature with id ${newFeatureId} to oblique source`,
|
|
338
|
+
);
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}),
|
|
342
|
+
];
|
|
343
|
+
sourceListeners = (): void => {
|
|
344
|
+
unByKey(listeners);
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const fetchFeaturesInView = (): void => {
|
|
349
|
+
if (
|
|
350
|
+
active &&
|
|
351
|
+
map.currentImage &&
|
|
352
|
+
currentImageName !== map.currentImage.name
|
|
353
|
+
) {
|
|
354
|
+
currentExtent = map
|
|
355
|
+
.getExtentOfCurrentImage()
|
|
356
|
+
.getCoordinatesInProjection(mercatorProjection);
|
|
357
|
+
source.forEachFeatureInExtent(currentExtent, (feature) => {
|
|
358
|
+
addFeature(feature).catch((_e) => {
|
|
359
|
+
getLogger('SourceObliqueSync').warning(
|
|
360
|
+
`Failed to add feature with id ${feature.getId()!} to oblique source`,
|
|
361
|
+
);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
source.forEachFeature((feature) => {
|
|
365
|
+
if (feature.getGeometry()?.[alreadyTransformedToImage]) {
|
|
366
|
+
addFeature(feature).catch((_e) => {
|
|
367
|
+
getLogger('SourceObliqueSync').warning(
|
|
368
|
+
`Failed to add feature with id ${feature.getId()!} to oblique source`,
|
|
369
|
+
);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
currentImageName = map.currentImage.name;
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const clearCurrentImage = (): void => {
|
|
378
|
+
featureListeners.forEach((listener): void => {
|
|
379
|
+
listener();
|
|
380
|
+
});
|
|
381
|
+
featureListeners.clear();
|
|
382
|
+
clearUpdatingTimeouts(updatingOblique);
|
|
383
|
+
clearUpdatingTimeouts(updatingMercator);
|
|
384
|
+
updatingOblique = {};
|
|
385
|
+
updatingMercator = {};
|
|
386
|
+
obliqueSource.getFeatures().forEach((f) => {
|
|
387
|
+
const original = f[originalFeatureSymbol];
|
|
388
|
+
if (original) {
|
|
389
|
+
delete original[obliqueGeometry];
|
|
390
|
+
const originalGeometry = original.getGeometry();
|
|
391
|
+
if (originalGeometry?.[alreadyTransformedToImage]) {
|
|
392
|
+
updateMercatorGeometry(original, f);
|
|
393
|
+
}
|
|
394
|
+
delete originalGeometry?.[alreadyTransformedToImage];
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
obliqueSource.clear(true);
|
|
398
|
+
currentImageName = undefined;
|
|
399
|
+
currentExtent = undefined;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const activate = (): void => {
|
|
403
|
+
active = true;
|
|
404
|
+
setSourceListeners();
|
|
405
|
+
imageChangedListener = map.imageChanged?.addEventListener(() => {
|
|
406
|
+
clearCurrentImage();
|
|
407
|
+
fetchFeaturesInView();
|
|
408
|
+
});
|
|
409
|
+
fetchFeaturesInView();
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const deactivate = (): void => {
|
|
413
|
+
active = false;
|
|
414
|
+
imageChangedListener?.();
|
|
415
|
+
sourceListeners();
|
|
416
|
+
clearCurrentImage();
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const destroy = (): void => {
|
|
420
|
+
obliqueSource.clear(true);
|
|
421
|
+
obliqueSource.dispose();
|
|
422
|
+
clearCurrentImage();
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
get active(): boolean {
|
|
427
|
+
return active;
|
|
428
|
+
},
|
|
429
|
+
get obliqueSource(): VectorSource {
|
|
430
|
+
return obliqueSource;
|
|
431
|
+
},
|
|
432
|
+
activate,
|
|
433
|
+
deactivate,
|
|
434
|
+
destroy,
|
|
435
|
+
};
|
|
436
|
+
}
|