@geode/opengeodeweb-front 10.16.0 → 10.16.1-rc.1

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.
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import ToolPanel from "@ogw_front/components/ToolPanel";
3
- import { applyCameraOptions } from "@ogw_front/utils/hybrid_viewer";
3
+ import { applyCameraOptions } from "@ogw_internal/stores/hybrid_viewer";
4
4
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
5
5
  import { newInstance as vtkAnnotatedCubeActor } from "@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor";
6
6
  import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
@@ -37,6 +37,13 @@ const camera_options = [
37
37
  hybridViewerStore.resetCamera();
38
38
  },
39
39
  },
40
+ {
41
+ tooltip: "Center on click",
42
+ icon: "mdi-crosshairs-question",
43
+ action: () => {
44
+ hybridViewerStore.is_picking = !hybridViewerStore.is_picking;
45
+ },
46
+ },
40
47
  {
41
48
  tooltip: "Camera orientation",
42
49
  icon: "mdi-rotate-3d",
@@ -1,16 +1,3 @@
1
- import {
2
- ORIENTATIONS,
3
- animateCamera,
4
- applyCameraOptions,
5
- computeAverageBrightness,
6
- getCameraOptions,
7
- } from "@ogw_front/utils/hybrid_viewer";
8
- import { dot } from "@kitware/vtk.js/Common/Core/Math";
9
- import { newInstance as vtkActor } from "@kitware/vtk.js/Rendering/Core/Actor";
10
- import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
11
- import { newInstance as vtkMapper } from "@kitware/vtk.js/Rendering/Core/Mapper";
12
- import { newInstance as vtkXMLPolyDataReader } from "@kitware/vtk.js/IO/XML/XMLPolyDataReader";
13
-
14
1
  import {
15
2
  ACTOR_COLOR,
16
3
  ALIGNMENT_THRESHOLD,
@@ -20,7 +7,17 @@ import {
20
7
  LONG_ANIMATION_DURATION,
21
8
  SHORT_ANIMATION_DURATION,
22
9
  WHEEL_TIME_OUT_MS,
23
- } from "@ogw_front/utils/vtk/constants";
10
+ applySnapshot,
11
+ computeAverageBrightness,
12
+ getCameraOptions,
13
+ performCameraOrientation,
14
+ performClickPicking,
15
+ } from "@ogw_internal/stores/hybrid_viewer";
16
+ import { newInstance as vtkActor } from "@kitware/vtk.js/Rendering/Core/Actor";
17
+ import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
18
+ import { newInstance as vtkMapper } from "@kitware/vtk.js/Rendering/Core/Mapper";
19
+ import { newInstance as vtkXMLPolyDataReader } from "@kitware/vtk.js/IO/XML/XMLPolyDataReader";
20
+
24
21
  import { Status } from "@ogw_front/utils/status";
25
22
  import { useDataStore } from "@ogw_front/stores/data";
26
23
  import { useViewerStore } from "@ogw_front/stores/viewer";
@@ -35,11 +32,21 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
35
32
  const camera_options = reactive({});
36
33
  const genericRenderWindow = reactive({});
37
34
  const is_moving = ref(false);
35
+ const is_picking = ref(false);
38
36
  const zScale = ref(1);
39
37
  let viewStream = undefined;
40
38
  let imageStyle = undefined;
41
39
  const gridActor = undefined;
42
40
 
41
+ watch(is_picking, (value) => {
42
+ const element = genericRenderWindow.value
43
+ ?.getApiSpecificRenderWindow()
44
+ ?.getCanvas()?.parentElement;
45
+ if (element) {
46
+ element.style.cursor = value ? "crosshair" : "default";
47
+ }
48
+ });
49
+
43
50
  const latestImage = ref(undefined);
44
51
  const offscreenCanvas =
45
52
  typeof document === "undefined" ? undefined : document.createElement("canvas");
@@ -153,37 +160,17 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
153
160
  }
154
161
 
155
162
  function setCameraOrientation(orientation) {
156
- const config = ORIENTATIONS[orientation.toLowerCase()];
157
- const renderer = genericRenderWindow.value.getRenderer();
158
- const camera = renderer.getActiveCamera();
159
- const startState = getCameraOptions(camera);
160
-
161
- applyCameraOptions(camera, {
162
- ...config,
163
- focal_point: [0, 0, 0],
164
- });
165
- renderer.resetCamera();
166
- const targetState = getCameraOptions(camera);
167
-
168
- applyCameraOptions(camera, startState);
169
-
170
- const alignment = dot(camera.getDirectionOfProjection(), config.position);
171
- const duration =
172
- alignment > ALIGNMENT_THRESHOLD ? LONG_ANIMATION_DURATION : SHORT_ANIMATION_DURATION;
173
- is_moving.value = true;
174
- imageStyle.opacity = 0;
175
-
176
- animateCamera({
177
- camera,
178
- startState,
179
- targetState,
180
- duration,
181
- bumpMultiplier: BUMP_MULTIPLIER,
182
- easeExponent: EASE_EXPONENT,
183
- onUpdate: () => genericRenderWindow.value.getRenderWindow().render(),
184
- onEnd: () => {
185
- is_moving.value = false;
186
- syncRemoteCamera();
163
+ performCameraOrientation(orientation, {
164
+ genericRenderWindow: genericRenderWindow.value,
165
+ is_moving,
166
+ imageStyle,
167
+ syncRemoteCamera,
168
+ constants: {
169
+ ALIGNMENT_THRESHOLD,
170
+ BUMP_MULTIPLIER,
171
+ EASE_EXPONENT,
172
+ LONG_ANIMATION_DURATION,
173
+ SHORT_ANIMATION_DURATION,
187
174
  },
188
175
  });
189
176
  }
@@ -219,11 +206,23 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
219
206
  useMousePressed({
220
207
  target: container,
221
208
  onPressed: (event) => {
222
- if (event.button === 0) {
223
- is_moving.value = true;
224
- event.stopPropagation();
225
- imageStyle.opacity = 0;
209
+ if (event.button !== 0) {
210
+ return;
226
211
  }
212
+ if (is_picking.value) {
213
+ performClickPicking(event, {
214
+ container: container.value.$el,
215
+ viewerStore,
216
+ viewer_schemas,
217
+ genericRenderWindow: genericRenderWindow.value,
218
+ syncRemoteCamera,
219
+ });
220
+ is_picking.value = false;
221
+ return;
222
+ }
223
+ is_moving.value = true;
224
+ event.stopPropagation();
225
+ imageStyle.opacity = 0;
227
226
  },
228
227
  onReleased: () => {
229
228
  if (!is_moving.value) {
@@ -279,21 +278,11 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
279
278
  }
280
279
 
281
280
  async function importStores(snapshot) {
282
- if (!snapshot) {
283
- return;
284
- }
285
- const z_scale = snapshot.zScale;
286
- if (typeof z_scale === "number") {
287
- await setZScaling(z_scale);
288
- }
289
-
290
- const { camera_options: snapshot_camera_options } = snapshot;
291
- if (snapshot_camera_options) {
292
- const renderer = genericRenderWindow.value.getRenderer();
293
- applyCameraOptions(renderer.getActiveCamera(), snapshot_camera_options);
294
- genericRenderWindow.value.getRenderWindow().render();
295
- syncRemoteCamera();
296
- }
281
+ await applySnapshot(snapshot, {
282
+ genericRenderWindow: genericRenderWindow.value,
283
+ setZScaling,
284
+ syncRemoteCamera,
285
+ });
297
286
  }
298
287
 
299
288
  function clear() {
@@ -323,6 +312,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
323
312
  setCameraOrientation,
324
313
  setContainer,
325
314
  zScale,
315
+ is_picking,
326
316
  clear,
327
317
  exportStores,
328
318
  importStores,
@@ -1,6 +1,26 @@
1
- import { SHORT_ANIMATION_DURATION } from "@ogw_front/utils/vtk/constants";
1
+ import { dot } from "@kitware/vtk.js/Common/Core/Math";
2
+
2
3
  const RGB_MAX = 255;
3
4
  const BACKGROUND_GREY_VALUE = 180;
5
+ const ACTOR_DARK_VALUE = 20;
6
+
7
+ const BACKGROUND_COLOR = [
8
+ BACKGROUND_GREY_VALUE / RGB_MAX,
9
+ BACKGROUND_GREY_VALUE / RGB_MAX,
10
+ BACKGROUND_GREY_VALUE / RGB_MAX,
11
+ ];
12
+ const ACTOR_COLOR = [
13
+ ACTOR_DARK_VALUE / RGB_MAX,
14
+ ACTOR_DARK_VALUE / RGB_MAX,
15
+ ACTOR_DARK_VALUE / RGB_MAX,
16
+ ];
17
+ const WHEEL_TIME_OUT_MS = 600;
18
+ const BUMP_MULTIPLIER = 0.2;
19
+ const ALIGNMENT_THRESHOLD = 0.9;
20
+ const LONG_ANIMATION_DURATION = 1000;
21
+ const SHORT_ANIMATION_DURATION = 500;
22
+ const EASE_EXPONENT = 1.1;
23
+
4
24
  const SAMPLE_SIZE = 10;
5
25
  const TOTAL_CHANNELS = 400;
6
26
  const RGBA_CHANNELS = 4;
@@ -95,6 +115,42 @@ function computeAverageBrightness(rect, options) {
95
115
  }
96
116
  }
97
117
 
118
+ function centerCameraOnPosition(camera, pickedPosition) {
119
+ if (!camera || !pickedPosition) {
120
+ return;
121
+ }
122
+ const focalPoint = camera.getFocalPoint();
123
+ const position = camera.getPosition();
124
+ camera.setFocalPoint(...pickedPosition);
125
+ camera.setPosition(
126
+ position[0] + pickedPosition[0] - focalPoint[0],
127
+ position[1] + pickedPosition[1] - focalPoint[1],
128
+ position[2] + pickedPosition[2] - focalPoint[2],
129
+ );
130
+ }
131
+
132
+ function performClickPicking(event, options) {
133
+ const { container, viewerStore, viewer_schemas, genericRenderWindow, syncRemoteCamera } = options;
134
+ const rect = container.getBoundingClientRect();
135
+ viewerStore.request(
136
+ viewer_schemas.opengeodeweb_viewer.viewer.get_point_position,
137
+ {
138
+ x: Math.round(event.clientX - rect.left),
139
+ y: Math.round(rect.height - (event.clientY - rect.top)),
140
+ },
141
+ {
142
+ response_function: ({ x, y, z }) => {
143
+ const pickedPos = [x, y, z];
144
+ if (pickedPos.some((val) => val !== 0)) {
145
+ centerCameraOnPosition(genericRenderWindow.getRenderer().getActiveCamera(), pickedPos);
146
+ genericRenderWindow.getRenderWindow().render();
147
+ syncRemoteCamera();
148
+ }
149
+ },
150
+ },
151
+ );
152
+ }
153
+
98
154
  function animateCamera(options) {
99
155
  const {
100
156
  camera,
@@ -140,10 +196,81 @@ function animateCamera(options) {
140
196
  requestAnimationFrame(animate);
141
197
  }
142
198
 
199
+ async function applySnapshot(snapshot, options) {
200
+ const { genericRenderWindow, setZScaling, syncRemoteCamera } = options;
201
+ if (!snapshot) {
202
+ return;
203
+ }
204
+ const z_scale = snapshot.zScale;
205
+ if (typeof z_scale === "number") {
206
+ await setZScaling(z_scale);
207
+ }
208
+ const { camera_options: snapshot_camera_options } = snapshot;
209
+ if (snapshot_camera_options) {
210
+ applyCameraOptions(
211
+ genericRenderWindow.getRenderer().getActiveCamera(),
212
+ snapshot_camera_options,
213
+ );
214
+ genericRenderWindow.getRenderWindow().render();
215
+ syncRemoteCamera();
216
+ }
217
+ }
218
+
219
+ function performCameraOrientation(orientation, options) {
220
+ const { genericRenderWindow, is_moving, imageStyle, syncRemoteCamera, constants } = options;
221
+ const config = ORIENTATIONS[orientation.toLowerCase()];
222
+ const renderer = genericRenderWindow.getRenderer();
223
+ const camera = renderer.getActiveCamera();
224
+ const startState = getCameraOptions(camera);
225
+
226
+ applyCameraOptions(camera, {
227
+ ...config,
228
+ focal_point: [0, 0, 0],
229
+ });
230
+ renderer.resetCamera();
231
+ const targetState = getCameraOptions(camera);
232
+
233
+ applyCameraOptions(camera, startState);
234
+
235
+ const alignment = dot(camera.getDirectionOfProjection(), config.position);
236
+ const duration =
237
+ alignment > constants.ALIGNMENT_THRESHOLD
238
+ ? constants.LONG_ANIMATION_DURATION
239
+ : constants.SHORT_ANIMATION_DURATION;
240
+ is_moving.value = true;
241
+ imageStyle.opacity = 0;
242
+
243
+ animateCamera({
244
+ camera,
245
+ startState,
246
+ targetState,
247
+ duration,
248
+ bumpMultiplier: constants.BUMP_MULTIPLIER,
249
+ easeExponent: constants.EASE_EXPONENT,
250
+ onUpdate: () => genericRenderWindow.getRenderWindow().render(),
251
+ onEnd: () => {
252
+ is_moving.value = false;
253
+ syncRemoteCamera();
254
+ },
255
+ });
256
+ }
257
+
143
258
  export {
259
+ BACKGROUND_COLOR,
260
+ ACTOR_COLOR,
261
+ WHEEL_TIME_OUT_MS,
262
+ BUMP_MULTIPLIER,
263
+ ALIGNMENT_THRESHOLD,
264
+ LONG_ANIMATION_DURATION,
265
+ SHORT_ANIMATION_DURATION,
266
+ EASE_EXPONENT,
144
267
  ORIENTATIONS,
145
268
  animateCamera,
146
269
  applyCameraOptions,
270
+ applySnapshot,
271
+ centerCameraOnPosition,
147
272
  computeAverageBrightness,
148
273
  getCameraOptions,
274
+ performCameraOrientation,
275
+ performClickPicking,
149
276
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.16.0",
3
+ "version": "10.16.1-rc.1",
4
4
  "description": "OpenSource Vue/Nuxt/Pinia/Vuetify framework for web applications",
5
5
  "homepage": "https://github.com/Geode-solutions/OpenGeodeWeb-Front",
6
6
  "bugs": {
@@ -34,8 +34,8 @@
34
34
  "build": ""
35
35
  },
36
36
  "dependencies": {
37
- "@geode/opengeodeweb-back": "latest",
38
- "@geode/opengeodeweb-viewer": "latest",
37
+ "@geode/opengeodeweb-back": "next",
38
+ "@geode/opengeodeweb-viewer": "next",
39
39
  "@google-cloud/run": "3.2.0",
40
40
  "@kitware/vtk.js": "33.3.0",
41
41
  "@mdi/font": "7.4.47",
@@ -1,31 +0,0 @@
1
- const RGB_MAX = 255;
2
- const BACKGROUND_GREY_VALUE = 180;
3
- const ACTOR_DARK_VALUE = 20;
4
-
5
- const BACKGROUND_COLOR = [
6
- BACKGROUND_GREY_VALUE / RGB_MAX,
7
- BACKGROUND_GREY_VALUE / RGB_MAX,
8
- BACKGROUND_GREY_VALUE / RGB_MAX,
9
- ];
10
- const ACTOR_COLOR = [
11
- ACTOR_DARK_VALUE / RGB_MAX,
12
- ACTOR_DARK_VALUE / RGB_MAX,
13
- ACTOR_DARK_VALUE / RGB_MAX,
14
- ];
15
- const WHEEL_TIME_OUT_MS = 600;
16
- const BUMP_MULTIPLIER = 0.2;
17
- const ALIGNMENT_THRESHOLD = 0.9;
18
- const LONG_ANIMATION_DURATION = 1000;
19
- const SHORT_ANIMATION_DURATION = 500;
20
- const EASE_EXPONENT = 1.1;
21
-
22
- export {
23
- BACKGROUND_COLOR,
24
- ACTOR_COLOR,
25
- WHEEL_TIME_OUT_MS,
26
- BUMP_MULTIPLIER,
27
- ALIGNMENT_THRESHOLD,
28
- LONG_ANIMATION_DURATION,
29
- SHORT_ANIMATION_DURATION,
30
- EASE_EXPONENT,
31
- };