@geode/opengeodeweb-front 10.18.1 → 10.18.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/app/assets/{scientific_colormaps.json → colormaps.json} +1109 -1104
- package/app/components/CameraOrientation.vue +1 -1
- package/app/components/ViewToolbar.vue +79 -3
- package/app/components/Viewer/Options/ColorMapPicker.vue +3 -3
- package/app/composables/project_manager.js +79 -81
- package/app/stores/camera_manager.js +7 -6
- package/app/stores/data.js +22 -19
- package/app/stores/data_style.js +8 -4
- package/app/stores/hybrid_viewer.js +80 -100
- package/app/stores/viewer.js +1 -1
- package/app/utils/colormap.js +4 -5
- package/internal/stores/data_style/model/common.js +14 -13
- package/internal/stores/data_style/state.js +11 -7
- package/internal/stores/hybrid_viewer.js +159 -172
- package/internal/stores/hybrid_viewer_camera.js +220 -0
- package/package.json +1 -1
- package/tests/unit/composables/project_manager.nuxt.test.js +3 -6
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LONG_ANIMATION_DURATION,
|
|
3
|
-
SHORT_ANIMATION_DURATION,
|
|
4
|
-
animateCamera,
|
|
5
|
-
computeAnimationDuration,
|
|
6
|
-
} from "@ogw_internal/stores/hybrid_viewer_camera_animation";
|
|
7
|
-
import { dot } from "@kitware/vtk.js/Common/Core/Math";
|
|
1
|
+
import { centerCameraOnPosition } from "./hybrid_viewer_camera";
|
|
8
2
|
|
|
9
3
|
const RGB_MAX = 255;
|
|
10
4
|
const BACKGROUND_GREY_VALUE = 180;
|
|
@@ -21,49 +15,12 @@ const ACTOR_COLOR = [
|
|
|
21
15
|
ACTOR_DARK_VALUE / RGB_MAX,
|
|
22
16
|
];
|
|
23
17
|
const WHEEL_TIME_OUT_MS = 600;
|
|
24
|
-
const
|
|
25
|
-
const ALIGNMENT_THRESHOLD = 0.9;
|
|
26
|
-
const EASE_EXPONENT = 1.1;
|
|
18
|
+
const HOVER_THROTTLE_MS = 50;
|
|
27
19
|
|
|
28
20
|
const SAMPLE_SIZE = 10;
|
|
29
21
|
const TOTAL_CHANNELS = 400;
|
|
30
22
|
const RGBA_CHANNELS = 4;
|
|
31
23
|
|
|
32
|
-
const ORIENTATIONS = {
|
|
33
|
-
zplus: { position: [0, 0, 1], view_up: [0, 1, 0] },
|
|
34
|
-
zminus: { position: [0, 0, -1], view_up: [0, 1, 0] },
|
|
35
|
-
yplus: { position: [0, 1, 0], view_up: [0, 0, 1] },
|
|
36
|
-
yminus: { position: [0, -1, 0], view_up: [0, 0, 1] },
|
|
37
|
-
xplus: { position: [1, 0, 0], view_up: [0, 0, 1] },
|
|
38
|
-
xminus: { position: [-1, 0, 0], view_up: [0, 0, 1] },
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
function getCameraOptions(camera) {
|
|
42
|
-
if (!camera?.getFocalPoint) {
|
|
43
|
-
return camera;
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
focal_point: [...(camera.getFocalPoint() ?? [])],
|
|
47
|
-
view_up: [...(camera.getViewUp() ?? [])],
|
|
48
|
-
position: [...(camera.getPosition() ?? [])],
|
|
49
|
-
view_angle: camera.getViewAngle(),
|
|
50
|
-
clipping_range: [...(camera.getClippingRange() ?? [])],
|
|
51
|
-
distance: camera.getDistance(),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function applyCameraOptions(camera, options) {
|
|
56
|
-
if (camera?.set && options) {
|
|
57
|
-
camera.set({
|
|
58
|
-
focalPoint: options.focal_point,
|
|
59
|
-
viewUp: options.view_up,
|
|
60
|
-
position: options.position,
|
|
61
|
-
viewAngle: options.view_angle,
|
|
62
|
-
clippingRange: options.clipping_range,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
24
|
function mapRect(rect, latestImage, canvasRect) {
|
|
68
25
|
const scaleX = latestImage.width / canvasRect.width;
|
|
69
26
|
const scaleY = latestImage.height / canvasRect.height;
|
|
@@ -113,20 +70,6 @@ function computeAverageBrightness(rect, options) {
|
|
|
113
70
|
}
|
|
114
71
|
}
|
|
115
72
|
|
|
116
|
-
function centerCameraOnPosition(camera, pickedPosition) {
|
|
117
|
-
if (!camera || !pickedPosition) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const focalPoint = camera.getFocalPoint();
|
|
121
|
-
const position = camera.getPosition();
|
|
122
|
-
camera.setFocalPoint(...pickedPosition);
|
|
123
|
-
camera.setPosition(
|
|
124
|
-
position[0] + pickedPosition[0] - focalPoint[0],
|
|
125
|
-
position[1] + pickedPosition[1] - focalPoint[1],
|
|
126
|
-
position[2] + pickedPosition[2] - focalPoint[2],
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
73
|
function performClickPicking(event, options) {
|
|
131
74
|
const { container, viewerStore, viewer_schemas, genericRenderWindow, syncRemoteCamera } = options;
|
|
132
75
|
const rect = container.getBoundingClientRect();
|
|
@@ -140,7 +83,8 @@ function performClickPicking(event, options) {
|
|
|
140
83
|
response_function: ({ x, y, z }) => {
|
|
141
84
|
const pickedPos = [x, y, z];
|
|
142
85
|
if (pickedPos.some((val) => val !== 0)) {
|
|
143
|
-
|
|
86
|
+
const camera = genericRenderWindow.getRenderer().getActiveCamera();
|
|
87
|
+
centerCameraOnPosition(camera, pickedPos);
|
|
144
88
|
genericRenderWindow.getRenderWindow().render();
|
|
145
89
|
syncRemoteCamera();
|
|
146
90
|
}
|
|
@@ -148,131 +92,179 @@ function performClickPicking(event, options) {
|
|
|
148
92
|
},
|
|
149
93
|
);
|
|
150
94
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
95
|
+
|
|
96
|
+
function performHoverHighlight(event, options) {
|
|
97
|
+
const {
|
|
98
|
+
is_hover_highlight,
|
|
99
|
+
genericRenderWindow,
|
|
100
|
+
viewerStore,
|
|
101
|
+
viewer_schemas,
|
|
102
|
+
hover_highlight_field_type,
|
|
103
|
+
hybridDb,
|
|
104
|
+
onResponse,
|
|
105
|
+
} = options;
|
|
106
|
+
if (!is_hover_highlight.value) {
|
|
154
107
|
return;
|
|
155
108
|
}
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
const { camera_options: snapshot_camera_options } = snapshot;
|
|
161
|
-
if (snapshot_camera_options) {
|
|
162
|
-
if (setCamera) {
|
|
163
|
-
setCamera(snapshot_camera_options);
|
|
164
|
-
} else {
|
|
165
|
-
applyCameraOptions(
|
|
166
|
-
genericRenderWindow.getRenderer().getActiveCamera(),
|
|
167
|
-
snapshot_camera_options,
|
|
168
|
-
);
|
|
169
|
-
genericRenderWindow.getRenderWindow().render();
|
|
170
|
-
syncRemoteCamera();
|
|
171
|
-
}
|
|
109
|
+
const container = genericRenderWindow.getContainer();
|
|
110
|
+
if (!container) {
|
|
111
|
+
return;
|
|
172
112
|
}
|
|
113
|
+
const rect = container.getBoundingClientRect();
|
|
114
|
+
viewerStore.request(
|
|
115
|
+
viewer_schemas.opengeodeweb_viewer.viewer.hover_highlight,
|
|
116
|
+
{
|
|
117
|
+
x: Math.round(event.clientX - rect.left),
|
|
118
|
+
y: Math.round(rect.height - (event.clientY - rect.top)),
|
|
119
|
+
field_type: hover_highlight_field_type.value,
|
|
120
|
+
ids: Object.keys(hybridDb),
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
response_function: onResponse,
|
|
124
|
+
},
|
|
125
|
+
);
|
|
173
126
|
}
|
|
174
127
|
|
|
175
|
-
function
|
|
176
|
-
const {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
imageStyle.opacity = 0;
|
|
183
|
-
}
|
|
184
|
-
animateCamera({
|
|
185
|
-
camera,
|
|
186
|
-
startState,
|
|
187
|
-
targetState: targetCameraOptions,
|
|
188
|
-
duration,
|
|
189
|
-
bumpMultiplier: 0,
|
|
190
|
-
easeExponent: EASE_EXPONENT,
|
|
191
|
-
onUpdate: () => genericRenderWindow.getRenderWindow().render(),
|
|
192
|
-
onEnd: () => {
|
|
193
|
-
applyCameraOptions(camera, targetCameraOptions);
|
|
194
|
-
genericRenderWindow.getRenderWindow().render();
|
|
195
|
-
is_moving.value = false;
|
|
196
|
-
syncRemoteCamera();
|
|
197
|
-
},
|
|
128
|
+
function performClearHoverHighlight(options) {
|
|
129
|
+
const { viewerStore, viewer_schemas, hover_highlight_field_type, hybridDb } = options;
|
|
130
|
+
viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.hover_highlight, {
|
|
131
|
+
x: -1,
|
|
132
|
+
y: -1,
|
|
133
|
+
field_type: hover_highlight_field_type.value,
|
|
134
|
+
ids: Object.keys(hybridDb),
|
|
198
135
|
});
|
|
199
136
|
}
|
|
200
137
|
|
|
201
|
-
function
|
|
202
|
-
const {
|
|
203
|
-
|
|
138
|
+
async function performAddItem(id, options) {
|
|
139
|
+
const {
|
|
140
|
+
genericRenderWindow,
|
|
141
|
+
dataStore,
|
|
142
|
+
vtkXMLPolyDataReader,
|
|
143
|
+
vtkActor,
|
|
144
|
+
vtkMapper,
|
|
145
|
+
actorColor,
|
|
146
|
+
hybridDb,
|
|
147
|
+
} = options;
|
|
148
|
+
if (!genericRenderWindow) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const reader = vtkXMLPolyDataReader(),
|
|
152
|
+
value = await dataStore.item(id);
|
|
153
|
+
await reader.parseAsArrayBuffer(new TextEncoder().encode(value.binary_light_viewable));
|
|
154
|
+
const actor = vtkActor(),
|
|
155
|
+
mapper = vtkMapper(),
|
|
156
|
+
polydata = reader.getOutputData(0);
|
|
157
|
+
mapper.setInputData(polydata);
|
|
158
|
+
actor.getProperty().setColor(actorColor);
|
|
159
|
+
actor.setMapper(mapper);
|
|
204
160
|
const renderer = genericRenderWindow.getRenderer();
|
|
205
|
-
const
|
|
206
|
-
|
|
161
|
+
const isFirst = renderer.getActors().length === 0;
|
|
162
|
+
renderer.addActor(actor);
|
|
163
|
+
if (isFirst) {
|
|
164
|
+
renderer.resetCamera();
|
|
165
|
+
}
|
|
166
|
+
hybridDb[id] = { actor, polydata, mapper };
|
|
167
|
+
}
|
|
207
168
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
169
|
+
async function performSetZScaling(z_scale, options) {
|
|
170
|
+
const { zScale, genericRenderWindow, gridActor, viewerStore, viewer_schemas, remoteRender } =
|
|
171
|
+
options;
|
|
172
|
+
zScale.value = z_scale;
|
|
173
|
+
const renderer = genericRenderWindow.getRenderer();
|
|
174
|
+
for (const actor of renderer.getActors()) {
|
|
175
|
+
if (actor !== gridActor) {
|
|
176
|
+
const scale = actor.getScale();
|
|
177
|
+
actor.setScale(scale[0], scale[1], z_scale);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
212
180
|
renderer.resetCamera();
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
alignment > ALIGNMENT_THRESHOLD ? LONG_ANIMATION_DURATION : SHORT_ANIMATION_DURATION;
|
|
220
|
-
is_moving.value = true;
|
|
221
|
-
imageStyle.opacity = 0;
|
|
222
|
-
|
|
223
|
-
animateCamera({
|
|
224
|
-
camera,
|
|
225
|
-
startState,
|
|
226
|
-
targetState,
|
|
227
|
-
duration,
|
|
228
|
-
bumpMultiplier: BUMP_MULTIPLIER,
|
|
229
|
-
easeExponent: EASE_EXPONENT,
|
|
230
|
-
onUpdate: () => genericRenderWindow.getRenderWindow().render(),
|
|
231
|
-
onEnd: () => {
|
|
232
|
-
is_moving.value = false;
|
|
233
|
-
syncRemoteCamera();
|
|
234
|
-
},
|
|
235
|
-
});
|
|
181
|
+
genericRenderWindow.getRenderWindow().render();
|
|
182
|
+
const schema = viewer_schemas?.opengeodeweb_viewer?.viewer?.set_z_scaling;
|
|
183
|
+
if (schema) {
|
|
184
|
+
await viewerStore.request(schema, { z_scale });
|
|
185
|
+
}
|
|
186
|
+
remoteRender();
|
|
236
187
|
}
|
|
237
188
|
|
|
238
|
-
|
|
189
|
+
function performSetContainer(options) {
|
|
239
190
|
const {
|
|
240
|
-
|
|
241
|
-
viewerStore,
|
|
242
|
-
viewer_schemas,
|
|
191
|
+
container,
|
|
243
192
|
genericRenderWindow,
|
|
244
|
-
|
|
193
|
+
imageStyleSetter,
|
|
194
|
+
resize,
|
|
195
|
+
useMousePressed,
|
|
196
|
+
useEventListener,
|
|
197
|
+
is_picking,
|
|
245
198
|
is_moving,
|
|
246
|
-
|
|
199
|
+
clickPickingCallback,
|
|
200
|
+
viewerStore,
|
|
201
|
+
viewer_schemas,
|
|
247
202
|
syncRemoteCamera,
|
|
203
|
+
throttledHoverHighlight,
|
|
204
|
+
wheelTimeoutMs,
|
|
205
|
+
wheelEventEndTimeout,
|
|
206
|
+
wheelTimeoutSetter,
|
|
248
207
|
} = options;
|
|
249
208
|
|
|
250
|
-
if (!
|
|
209
|
+
if (!container.value) {
|
|
251
210
|
return;
|
|
252
211
|
}
|
|
253
212
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
} else {
|
|
261
|
-
bounds = hybridDb[id].actor.getBounds();
|
|
262
|
-
}
|
|
213
|
+
genericRenderWindow.setContainer(container.value.$el);
|
|
214
|
+
const webGLRenderWindow = genericRenderWindow.getApiSpecificRenderWindow();
|
|
215
|
+
webGLRenderWindow.setUseBackgroundImage(true);
|
|
216
|
+
const imageStyle = webGLRenderWindow.getReferenceByName("bgImage").style;
|
|
217
|
+
Object.assign(imageStyle, { transition: "opacity 0.1s ease-in", zIndex: 1 });
|
|
218
|
+
imageStyleSetter(imageStyle);
|
|
263
219
|
|
|
264
|
-
|
|
265
|
-
const camera = renderer.getActiveCamera();
|
|
266
|
-
const startOptions = getCameraOptions(camera);
|
|
267
|
-
renderer.resetCamera(bounds);
|
|
268
|
-
const targetOptions = getCameraOptions(camera);
|
|
269
|
-
applyCameraOptions(camera, startOptions);
|
|
220
|
+
resize(container.value.$el.offsetWidth, container.value.$el.offsetHeight);
|
|
270
221
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
222
|
+
useMousePressed({
|
|
223
|
+
target: container,
|
|
224
|
+
onPressed: (event) => {
|
|
225
|
+
if (event.button !== 0) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (is_picking.value) {
|
|
229
|
+
clickPickingCallback(event, {
|
|
230
|
+
container: container.value.$el,
|
|
231
|
+
viewerStore,
|
|
232
|
+
viewer_schemas,
|
|
233
|
+
genericRenderWindow,
|
|
234
|
+
syncRemoteCamera,
|
|
235
|
+
});
|
|
236
|
+
is_picking.value = false;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
is_moving.value = true;
|
|
240
|
+
event.stopPropagation();
|
|
241
|
+
imageStyle.opacity = 0;
|
|
242
|
+
},
|
|
243
|
+
onReleased: () => {
|
|
244
|
+
if (is_moving.value) {
|
|
245
|
+
is_moving.value = false;
|
|
246
|
+
syncRemoteCamera();
|
|
247
|
+
}
|
|
248
|
+
is_moving.value = false;
|
|
249
|
+
genericRenderWindow.getRenderer().resetCameraClippingRange();
|
|
250
|
+
syncRemoteCamera();
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
useEventListener(container, "mousemove", throttledHoverHighlight);
|
|
255
|
+
useEventListener(container, "wheel", () => {
|
|
256
|
+
is_moving.value = true;
|
|
257
|
+
if (imageStyle) {
|
|
258
|
+
imageStyle.opacity = 0;
|
|
259
|
+
}
|
|
260
|
+
clearTimeout(wheelEventEndTimeout);
|
|
261
|
+
wheelTimeoutSetter(
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
is_moving.value = false;
|
|
264
|
+
genericRenderWindow.getRenderer().resetCameraClippingRange();
|
|
265
|
+
syncRemoteCamera();
|
|
266
|
+
}, wheelTimeoutMs),
|
|
267
|
+
);
|
|
276
268
|
});
|
|
277
269
|
}
|
|
278
270
|
|
|
@@ -280,17 +272,12 @@ export {
|
|
|
280
272
|
BACKGROUND_COLOR,
|
|
281
273
|
ACTOR_COLOR,
|
|
282
274
|
WHEEL_TIME_OUT_MS,
|
|
283
|
-
|
|
284
|
-
ALIGNMENT_THRESHOLD,
|
|
285
|
-
EASE_EXPONENT,
|
|
286
|
-
ORIENTATIONS,
|
|
287
|
-
applyCameraOptions,
|
|
288
|
-
applySnapshot,
|
|
289
|
-
centerCameraOnPosition,
|
|
275
|
+
HOVER_THROTTLE_MS,
|
|
290
276
|
computeAverageBrightness,
|
|
291
|
-
|
|
292
|
-
|
|
277
|
+
performAddItem,
|
|
278
|
+
performClearHoverHighlight,
|
|
293
279
|
performClickPicking,
|
|
294
|
-
|
|
295
|
-
|
|
280
|
+
performHoverHighlight,
|
|
281
|
+
performSetContainer,
|
|
282
|
+
performSetZScaling,
|
|
296
283
|
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LONG_ANIMATION_DURATION,
|
|
3
|
+
SHORT_ANIMATION_DURATION,
|
|
4
|
+
animateCamera,
|
|
5
|
+
computeAnimationDuration,
|
|
6
|
+
} from "@ogw_internal/stores/hybrid_viewer_camera_animation";
|
|
7
|
+
import { dot } from "@kitware/vtk.js/Common/Core/Math";
|
|
8
|
+
|
|
9
|
+
const BUMP_MULTIPLIER = 0.2;
|
|
10
|
+
const ALIGNMENT_THRESHOLD = 0.9;
|
|
11
|
+
const EASE_EXPONENT = 1.1;
|
|
12
|
+
|
|
13
|
+
const ORIENTATIONS = {
|
|
14
|
+
zplus: { position: [0, 0, 1], view_up: [0, 1, 0] },
|
|
15
|
+
zminus: { position: [0, 0, -1], view_up: [0, 1, 0] },
|
|
16
|
+
yplus: { position: [0, 1, 0], view_up: [0, 0, 1] },
|
|
17
|
+
yminus: { position: [0, -1, 0], view_up: [0, 0, 1] },
|
|
18
|
+
xplus: { position: [1, 0, 0], view_up: [0, 0, 1] },
|
|
19
|
+
xminus: { position: [-1, 0, 0], view_up: [0, 0, 1] },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getCameraOptions(camera) {
|
|
23
|
+
if (!camera?.getFocalPoint) {
|
|
24
|
+
return camera;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
focal_point: [...(camera.getFocalPoint() ?? [])],
|
|
28
|
+
view_up: [...(camera.getViewUp() ?? [])],
|
|
29
|
+
position: [...(camera.getPosition() ?? [])],
|
|
30
|
+
view_angle: camera.getViewAngle(),
|
|
31
|
+
clipping_range: [...(camera.getClippingRange() ?? [])],
|
|
32
|
+
distance: camera.getDistance(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function applyCameraOptions(camera, options) {
|
|
37
|
+
if (camera?.set && options) {
|
|
38
|
+
camera.set({
|
|
39
|
+
focalPoint: options.focal_point,
|
|
40
|
+
viewUp: options.view_up,
|
|
41
|
+
position: options.position,
|
|
42
|
+
viewAngle: options.view_angle,
|
|
43
|
+
clippingRange: options.clipping_range,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function centerCameraOnPosition(camera, pickedPosition) {
|
|
49
|
+
if (!camera || !pickedPosition) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const focalPoint = camera.getFocalPoint();
|
|
53
|
+
const position = camera.getPosition();
|
|
54
|
+
camera.setFocalPoint(...pickedPosition);
|
|
55
|
+
camera.setPosition(
|
|
56
|
+
position[0] + pickedPosition[0] - focalPoint[0],
|
|
57
|
+
position[1] + pickedPosition[1] - focalPoint[1],
|
|
58
|
+
position[2] + pickedPosition[2] - focalPoint[2],
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function performSetCamera(targetCameraOptions, options) {
|
|
63
|
+
const { genericRenderWindow, is_moving, imageStyle, syncRemoteCamera } = options;
|
|
64
|
+
const camera = genericRenderWindow.getRenderer().getActiveCamera();
|
|
65
|
+
const startState = getCameraOptions(camera);
|
|
66
|
+
const duration = computeAnimationDuration(startState, targetCameraOptions);
|
|
67
|
+
is_moving.value = true;
|
|
68
|
+
if (imageStyle) {
|
|
69
|
+
imageStyle.opacity = 0;
|
|
70
|
+
}
|
|
71
|
+
animateCamera({
|
|
72
|
+
camera,
|
|
73
|
+
startState,
|
|
74
|
+
targetState: targetCameraOptions,
|
|
75
|
+
duration,
|
|
76
|
+
bumpMultiplier: 0,
|
|
77
|
+
easeExponent: EASE_EXPONENT,
|
|
78
|
+
onUpdate: () => genericRenderWindow.getRenderWindow().render(),
|
|
79
|
+
onEnd: () => {
|
|
80
|
+
applyCameraOptions(camera, targetCameraOptions);
|
|
81
|
+
genericRenderWindow.getRenderWindow().render();
|
|
82
|
+
is_moving.value = false;
|
|
83
|
+
syncRemoteCamera();
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function performCameraOrientation(orientation, options) {
|
|
89
|
+
const { genericRenderWindow, is_moving, imageStyle, syncRemoteCamera } = options;
|
|
90
|
+
const config = ORIENTATIONS[orientation.toLowerCase()];
|
|
91
|
+
const renderer = genericRenderWindow.getRenderer();
|
|
92
|
+
const camera = renderer.getActiveCamera();
|
|
93
|
+
const startState = getCameraOptions(camera);
|
|
94
|
+
|
|
95
|
+
applyCameraOptions(camera, {
|
|
96
|
+
...config,
|
|
97
|
+
focal_point: [0, 0, 0],
|
|
98
|
+
});
|
|
99
|
+
renderer.resetCamera();
|
|
100
|
+
const targetState = getCameraOptions(camera);
|
|
101
|
+
|
|
102
|
+
applyCameraOptions(camera, startState);
|
|
103
|
+
|
|
104
|
+
const alignment = dot(camera.getDirectionOfProjection(), config.position);
|
|
105
|
+
const duration =
|
|
106
|
+
alignment > ALIGNMENT_THRESHOLD ? LONG_ANIMATION_DURATION : SHORT_ANIMATION_DURATION;
|
|
107
|
+
is_moving.value = true;
|
|
108
|
+
imageStyle.opacity = 0;
|
|
109
|
+
|
|
110
|
+
animateCamera({
|
|
111
|
+
camera,
|
|
112
|
+
startState,
|
|
113
|
+
targetState,
|
|
114
|
+
duration,
|
|
115
|
+
bumpMultiplier: BUMP_MULTIPLIER,
|
|
116
|
+
easeExponent: EASE_EXPONENT,
|
|
117
|
+
onUpdate: () => genericRenderWindow.getRenderWindow().render(),
|
|
118
|
+
onEnd: () => {
|
|
119
|
+
is_moving.value = false;
|
|
120
|
+
syncRemoteCamera();
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function performFocusCameraOnObject(id, options) {
|
|
126
|
+
const {
|
|
127
|
+
hybridDb,
|
|
128
|
+
viewerStore,
|
|
129
|
+
viewer_schemas,
|
|
130
|
+
genericRenderWindow,
|
|
131
|
+
block_ids = [],
|
|
132
|
+
is_moving,
|
|
133
|
+
imageStyle,
|
|
134
|
+
syncRemoteCamera,
|
|
135
|
+
} = options;
|
|
136
|
+
|
|
137
|
+
if (!hybridDb[id]) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let bounds = [];
|
|
142
|
+
if (block_ids.length > 0) {
|
|
143
|
+
bounds = await viewerStore.request(viewer_schemas.opengeodeweb_viewer.model.get_blocks_bounds, {
|
|
144
|
+
id,
|
|
145
|
+
block_ids,
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
bounds = hybridDb[id].actor.getBounds();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const renderer = genericRenderWindow.getRenderer();
|
|
152
|
+
const camera = renderer.getActiveCamera();
|
|
153
|
+
const startOptions = getCameraOptions(camera);
|
|
154
|
+
renderer.resetCamera(bounds);
|
|
155
|
+
const targetOptions = getCameraOptions(camera);
|
|
156
|
+
applyCameraOptions(camera, startOptions);
|
|
157
|
+
|
|
158
|
+
performSetCamera(targetOptions, {
|
|
159
|
+
genericRenderWindow,
|
|
160
|
+
is_moving,
|
|
161
|
+
imageStyle,
|
|
162
|
+
syncRemoteCamera,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function performSyncRemoteCamera(options) {
|
|
167
|
+
const { genericRenderWindow, viewerStore, viewer_schemas, remoteRender, camera_options } =
|
|
168
|
+
options;
|
|
169
|
+
const camera = genericRenderWindow.getRenderer().getActiveCamera();
|
|
170
|
+
const options_camera = getCameraOptions(camera);
|
|
171
|
+
viewerStore.request(
|
|
172
|
+
viewer_schemas.opengeodeweb_viewer.viewer.update_camera,
|
|
173
|
+
{ camera_options: options_camera },
|
|
174
|
+
{
|
|
175
|
+
response_function: () => {
|
|
176
|
+
remoteRender();
|
|
177
|
+
Object.assign(camera_options, options_camera);
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function applySnapshot(snapshot, options) {
|
|
184
|
+
const { genericRenderWindow, setZScaling, syncRemoteCamera, setCamera } = options;
|
|
185
|
+
if (!snapshot) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const z_scale = snapshot.zScale;
|
|
189
|
+
if (typeof z_scale === "number") {
|
|
190
|
+
await setZScaling(z_scale);
|
|
191
|
+
}
|
|
192
|
+
const { camera_options: snapshot_camera_options } = snapshot;
|
|
193
|
+
if (snapshot_camera_options) {
|
|
194
|
+
if (setCamera) {
|
|
195
|
+
setCamera(snapshot_camera_options);
|
|
196
|
+
} else {
|
|
197
|
+
applyCameraOptions(
|
|
198
|
+
genericRenderWindow.getRenderer().getActiveCamera(),
|
|
199
|
+
snapshot_camera_options,
|
|
200
|
+
);
|
|
201
|
+
genericRenderWindow.getRenderWindow().render();
|
|
202
|
+
syncRemoteCamera();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
BUMP_MULTIPLIER,
|
|
209
|
+
ALIGNMENT_THRESHOLD,
|
|
210
|
+
EASE_EXPONENT,
|
|
211
|
+
ORIENTATIONS,
|
|
212
|
+
applyCameraOptions,
|
|
213
|
+
applySnapshot,
|
|
214
|
+
centerCameraOnPosition,
|
|
215
|
+
getCameraOptions,
|
|
216
|
+
performCameraOrientation,
|
|
217
|
+
performFocusCameraOnObject,
|
|
218
|
+
performSetCamera,
|
|
219
|
+
performSyncRemoteCamera,
|
|
220
|
+
};
|
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
6
6
|
|
|
7
7
|
// Local imports
|
|
8
|
+
import { exportProject, importProject } from "@ogw_front/composables/project_manager";
|
|
8
9
|
import { appMode } from "@ogw_front/utils/local/app_mode";
|
|
9
10
|
import { setupActivePinia } from "@ogw_tests/utils";
|
|
10
|
-
import { useProjectManager } from "@ogw_front/composables/project_manager";
|
|
11
11
|
|
|
12
12
|
// Constants
|
|
13
13
|
const PANEL_WIDTH = 300;
|
|
@@ -245,7 +245,6 @@ describe("projectManager composable (compact)", () => {
|
|
|
245
245
|
});
|
|
246
246
|
|
|
247
247
|
test("exportProject", async () => {
|
|
248
|
-
const { exportProject } = useProjectManager();
|
|
249
248
|
const { default: fileDownload } = await import("js-file-download");
|
|
250
249
|
|
|
251
250
|
await exportProject();
|
|
@@ -254,24 +253,22 @@ describe("projectManager composable (compact)", () => {
|
|
|
254
253
|
});
|
|
255
254
|
|
|
256
255
|
test("importProjectFile with snapshot - Viewer and Stores", async () => {
|
|
257
|
-
const { importProjectFile } = useProjectManager();
|
|
258
256
|
const file = new Blob(['{"dataBase":{"db":{}}}'], {
|
|
259
257
|
type: "application/json",
|
|
260
258
|
});
|
|
261
259
|
|
|
262
|
-
await
|
|
260
|
+
await importProject(file);
|
|
263
261
|
|
|
264
262
|
verifyViewerCalls();
|
|
265
263
|
verifyStoreImports();
|
|
266
264
|
});
|
|
267
265
|
|
|
268
266
|
test("importProjectFile with snapshot - Data and Rendering", async () => {
|
|
269
|
-
const { importProjectFile } = useProjectManager();
|
|
270
267
|
const file = new Blob(['{"dataBase":{"db":{}}}'], {
|
|
271
268
|
type: "application/json",
|
|
272
269
|
});
|
|
273
270
|
|
|
274
|
-
await
|
|
271
|
+
await importProject(file);
|
|
275
272
|
|
|
276
273
|
verifyDataManagement();
|
|
277
274
|
verifyRemaining();
|