@geode/opengeodeweb-front 10.34.0-rc.8 → 10.34.0
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/{server → .build/server}/utils/app_config.js +10 -9
- package/{server → .build/server}/utils/cleanup.js +31 -17
- package/{server → .build/server}/utils/cloud.js +1 -4
- package/{server → .build/server}/utils/microservices.js +21 -9
- package/{server → .build/server}/utils/path.js +4 -4
- package/{server → .build/server}/utils/scripts.js +9 -9
- package/.build/server/utils/server_config.js +51 -0
- package/.build/server/utils/stream.js +6 -0
- package/{server → .build/server}/utils/ws_client.js +18 -3
- package/{shared → .build/shared}/scripts.js +10 -10
- package/.build/shared/utils/call_raw.js +31 -0
- package/{shared → .build/shared}/utils/call_schema.js +2 -2
- package/.build/shared/utils/fetch_raw.js +52 -0
- package/{shared → .build/shared}/utils/fetch_schema.js +2 -2
- package/{shared → .build/shared}/utils/file.js +3 -1
- package/{shared → .build/shared}/utils/response_handlers/load.js +10 -7
- package/{shared → .build/shared}/utils/validate_schema.js +1 -1
- package/app/components/ActionButton.vue +6 -6
- package/app/components/CameraManager/List.vue +5 -5
- package/app/components/CameraManager/Saver.vue +3 -5
- package/app/components/CameraManager.vue +6 -4
- package/app/components/CameraOrientation.vue +12 -12
- package/app/components/ClippingPlaneCard.vue +4 -2
- package/app/components/ClippingPlanes.vue +8 -8
- package/app/components/CrsSelector.vue +9 -10
- package/app/components/DeleteDialog.vue +4 -2
- package/app/components/DragAndDrop.vue +10 -12
- package/app/components/DragAndDropInternal/DragAndDropInline.vue +4 -2
- package/app/components/ExtensionSelector.vue +4 -4
- package/app/components/FeedBack/ErrorBanner.vue +3 -1
- package/app/components/FeedBack/Snackers.vue +4 -3
- package/app/components/FileSelector.vue +10 -8
- package/app/components/FileUploader.vue +11 -11
- package/app/components/GlassCard.vue +1 -1
- package/app/components/HybridRenderingView.vue +7 -5
- package/app/components/HybridViewerTooltip.vue +7 -7
- package/app/components/Launcher.vue +1 -1
- package/app/components/Loading/EcoMessages.vue +9 -3
- package/app/components/Loading.vue +2 -2
- package/app/components/MissingFilesSelector.vue +12 -10
- package/app/components/ObjectSelector.vue +10 -9
- package/app/components/PackagesVersions.vue +6 -5
- package/app/components/Recaptcha.vue +3 -3
- package/app/components/RemoteRenderingView.vue +6 -7
- package/app/components/Ruler.vue +3 -3
- package/app/components/Screenshot.vue +6 -6
- package/app/components/SearchBar.vue +4 -2
- package/app/components/ShrinkFilter.vue +7 -7
- package/app/components/Step.vue +6 -5
- package/app/components/Stepper.vue +4 -3
- package/app/components/ToolPanel.vue +6 -3
- package/app/components/ViewToolbar.vue +25 -28
- package/app/components/Viewer/ContextMenu/CenterButton.vue +7 -5
- package/app/components/Viewer/ContextMenu/CircularItems.vue +3 -3
- package/app/components/Viewer/ContextMenu/ContextMenu.vue +22 -19
- package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +10 -8
- package/app/components/Viewer/ContextMenu/InfoCard.vue +11 -12
- package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +13 -17
- package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +11 -15
- package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +12 -16
- package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +8 -12
- package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +11 -15
- package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +11 -15
- package/app/components/Viewer/Generic/Model/BlocksOptions.vue +67 -38
- package/app/components/Viewer/Generic/Model/CornersOptions.vue +53 -23
- package/app/components/Viewer/Generic/Model/EdgesOptions.vue +1 -3
- package/app/components/Viewer/Generic/Model/LinesOptions.vue +67 -38
- package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +31 -15
- package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +2 -3
- package/app/components/Viewer/Generic/Model/PointsOptions.vue +6 -6
- package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +69 -38
- package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +64 -46
- package/app/components/Viewer/ObjectTree/Base/Controls.vue +5 -5
- package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +13 -9
- package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +5 -5
- package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +10 -10
- package/app/components/Viewer/ObjectTree/Box.vue +6 -4
- package/app/components/Viewer/ObjectTree/Layout.vue +23 -21
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +14 -14
- package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +59 -24
- package/app/components/Viewer/Options/AttributeColorBar.vue +4 -2
- package/app/components/Viewer/Options/AttributeRangeSelector.vue +4 -2
- package/app/components/Viewer/Options/AttributeSelector.vue +7 -9
- package/app/components/Viewer/Options/ColorMapList.vue +15 -13
- package/app/components/Viewer/Options/ColorMapPicker.vue +4 -4
- package/app/components/Viewer/Options/ColorPicker.vue +223 -41
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +16 -16
- package/app/components/Viewer/Options/ColormapQuickPicker.vue +7 -5
- package/app/components/Viewer/Options/OptionsSection.vue +1 -1
- package/app/components/Viewer/Options/TextureItem.vue +8 -6
- package/app/components/Viewer/Options/TexturesSelector.vue +1 -1
- package/app/components/Viewer/OverlappingObjectsPicker.vue +8 -9
- package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +2 -6
- package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +12 -16
- package/app/components/Viewer/Surface/PolygonsOptions.vue +12 -16
- package/app/components/Viewer/Ui.vue +2 -2
- package/app/components/Wrapper.vue +1 -4
- package/app/components/ZScaling.vue +5 -3
- package/app/components/csv-preview/CsvPreviewer.vue +38 -37
- package/app/components/csv-preview/CsvSettings.vue +6 -4
- package/app/components/csv-preview/CsvTable.vue +1 -1
- package/app/composables/batch_style.ts +5 -6
- package/app/composables/clipping_planes_widget.ts +73 -181
- package/app/composables/clipping_planes_widget_entries.ts +189 -0
- package/app/composables/copy_to_clipboard.ts +7 -0
- package/app/composables/global_attribute_style.ts +163 -83
- package/app/composables/hover_highlight.ts +46 -14
- package/app/composables/model_collections.ts +26 -13
- package/app/composables/model_components.ts +26 -13
- package/app/composables/project_manager.ts +76 -19
- package/app/composables/responsive_middle_truncate.ts +13 -13
- package/app/composables/stepper_tree.ts +34 -11
- package/app/composables/tree_filter.ts +66 -44
- package/app/composables/tree_keyboard_nav.ts +25 -11
- package/app/composables/tree_scroll.ts +44 -14
- package/app/composables/use_adaptive_styles.ts +66 -23
- package/app/composables/use_overlapping_picker.ts +66 -16
- package/app/composables/use_quick_colormap.ts +16 -5
- package/app/composables/virtual_tree.ts +75 -43
- package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
- package/app/plugins/auto_store_register.ts +2 -7
- package/app/plugins/click_outside_ignore_snackbars.client.ts +39 -0
- package/app/stores/app.ts +57 -192
- package/app/stores/app_helpers/extension.ts +179 -0
- package/app/stores/back.ts +37 -21
- package/app/stores/camera_manager.ts +22 -20
- package/app/stores/cloud.ts +17 -13
- package/app/stores/data.ts +88 -47
- package/app/stores/data_helpers/collections.ts +36 -38
- package/app/stores/data_helpers/mesh.ts +45 -36
- package/app/stores/data_style.ts +50 -28
- package/app/stores/feedback.ts +6 -6
- package/app/stores/hybrid_viewer.ts +41 -52
- package/app/stores/infra.ts +39 -37
- package/app/stores/menu.ts +23 -14
- package/app/stores/treeview.ts +72 -42
- package/app/stores/viewer.ts +39 -27
- package/app/utils/attributes.ts +3 -3
- package/app/utils/clipping_planes.ts +111 -14
- package/app/utils/color_picker.ts +57 -0
- package/app/utils/colormap.ts +58 -35
- package/app/utils/default_styles/index.ts +2 -2
- package/app/utils/default_styles/meshes.ts +107 -13
- package/app/utils/default_styles/models.ts +83 -14
- package/app/utils/extension.ts +47 -20
- package/app/utils/import_workflow.ts +21 -13
- package/app/utils/name_cleaner.ts +1 -1
- package/app/utils/string.ts +1 -1
- package/app/utils/treeview.ts +2 -2
- package/internal/database/base_database.ts +7 -3
- package/internal/database/database.ts +36 -26
- package/internal/database/extended_database.ts +1 -1
- package/internal/stores/data_style/mesh/cells/cell.ts +70 -34
- package/internal/stores/data_style/mesh/cells/color.ts +12 -6
- package/internal/stores/data_style/mesh/cells/common.ts +18 -8
- package/internal/stores/data_style/mesh/cells/index.ts +122 -42
- package/internal/stores/data_style/mesh/cells/textures.ts +12 -6
- package/internal/stores/data_style/mesh/cells/vertex.ts +75 -34
- package/internal/stores/data_style/mesh/cells/visibility.ts +15 -4
- package/internal/stores/data_style/mesh/edges/color.ts +12 -6
- package/internal/stores/data_style/mesh/edges/common.ts +14 -6
- package/internal/stores/data_style/mesh/edges/edge.ts +71 -39
- package/internal/stores/data_style/mesh/edges/index.ts +117 -42
- package/internal/stores/data_style/mesh/edges/vertex.ts +76 -39
- package/internal/stores/data_style/mesh/edges/visibility.ts +15 -4
- package/internal/stores/data_style/mesh/edges/width.ts +12 -4
- package/internal/stores/data_style/mesh/index.ts +30 -11
- package/internal/stores/data_style/mesh/points/color.ts +12 -6
- package/internal/stores/data_style/mesh/points/common.ts +21 -8
- package/internal/stores/data_style/mesh/points/index.ts +101 -50
- package/internal/stores/data_style/mesh/points/size.ts +12 -4
- package/internal/stores/data_style/mesh/points/vertex.ts +75 -34
- package/internal/stores/data_style/mesh/points/visibility.ts +17 -7
- package/internal/stores/data_style/mesh/polygons/color.ts +12 -6
- package/internal/stores/data_style/mesh/polygons/common.ts +23 -6
- package/internal/stores/data_style/mesh/polygons/index.ts +130 -70
- package/internal/stores/data_style/mesh/polygons/polygon.ts +77 -43
- package/internal/stores/data_style/mesh/polygons/textures.ts +12 -6
- package/internal/stores/data_style/mesh/polygons/vertex.ts +79 -39
- package/internal/stores/data_style/mesh/polygons/visibility.ts +16 -6
- package/internal/stores/data_style/mesh/polyhedra/color.ts +12 -6
- package/internal/stores/data_style/mesh/polyhedra/common.ts +14 -6
- package/internal/stores/data_style/mesh/polyhedra/index.ts +115 -56
- package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +80 -39
- package/internal/stores/data_style/mesh/polyhedra/vertex.ts +79 -39
- package/internal/stores/data_style/mesh/polyhedra/visibility.ts +16 -6
- package/internal/stores/data_style/model/blocks/color.ts +43 -13
- package/internal/stores/data_style/model/blocks/common.ts +21 -6
- package/internal/stores/data_style/model/blocks/index.ts +89 -59
- package/internal/stores/data_style/model/blocks/polyhedron.ts +101 -44
- package/internal/stores/data_style/model/blocks/vertex.ts +107 -42
- package/internal/stores/data_style/model/blocks/visibility.ts +17 -4
- package/internal/stores/data_style/model/color.ts +171 -83
- package/internal/stores/data_style/model/common.ts +70 -21
- package/internal/stores/data_style/model/corners/color.ts +43 -11
- package/internal/stores/data_style/model/corners/common.ts +25 -6
- package/internal/stores/data_style/model/corners/index.ts +66 -41
- package/internal/stores/data_style/model/corners/vertex.ts +105 -74
- package/internal/stores/data_style/model/corners/visibility.ts +19 -4
- package/internal/stores/data_style/model/edges/common.ts +12 -4
- package/internal/stores/data_style/model/edges/index.ts +2 -1
- package/internal/stores/data_style/model/edges/visibility.ts +24 -7
- package/internal/stores/data_style/model/index.ts +24 -11
- package/internal/stores/data_style/model/lines/color.ts +41 -11
- package/internal/stores/data_style/model/lines/common.ts +17 -6
- package/internal/stores/data_style/model/lines/edge.ts +105 -42
- package/internal/stores/data_style/model/lines/index.ts +86 -59
- package/internal/stores/data_style/model/lines/vertex.ts +105 -42
- package/internal/stores/data_style/model/lines/visibility.ts +17 -4
- package/internal/stores/data_style/model/points/common.ts +8 -4
- package/internal/stores/data_style/model/points/index.ts +10 -3
- package/internal/stores/data_style/model/points/size.ts +12 -4
- package/internal/stores/data_style/model/points/visibility.ts +16 -6
- package/internal/stores/data_style/model/selection.ts +80 -58
- package/internal/stores/data_style/model/surfaces/color.ts +41 -11
- package/internal/stores/data_style/model/surfaces/common.ts +23 -6
- package/internal/stores/data_style/model/surfaces/index.ts +89 -59
- package/internal/stores/data_style/model/surfaces/polygon.ts +107 -67
- package/internal/stores/data_style/model/surfaces/vertex.ts +111 -67
- package/internal/stores/data_style/model/surfaces/visibility.ts +18 -5
- package/internal/stores/data_style/model/visibility.ts +82 -20
- package/internal/stores/data_style/state.ts +77 -65
- package/internal/stores/hybrid_viewer/brightness.ts +49 -31
- package/internal/stores/hybrid_viewer/camera.ts +191 -177
- package/internal/stores/hybrid_viewer/camera_animation.ts +11 -10
- package/internal/stores/hybrid_viewer/core.ts +64 -0
- package/internal/stores/hybrid_viewer/filters.ts +10 -16
- package/internal/stores/hybrid_viewer/highlight.ts +91 -130
- package/internal/stores/hybrid_viewer/ruler.ts +24 -15
- package/internal/stores/hybrid_viewer/scene.ts +96 -117
- package/internal/stores/hybrid_viewer/viewport.ts +74 -65
- package/internal/stores/hybrid_viewer/vtk_types.ts +13 -29
- package/internal/utils/api_fetch.ts +54 -23
- package/internal/utils/upload_file.ts +74 -53
- package/internal/utils/viewer_call.ts +22 -13
- package/internal/utils/ws_client.ts +24 -13
- package/nuxt.config.ts +58 -1
- package/package.json +20 -8
- package/server/api/cloud/extensions/run.post.ts +6 -10
- package/server/api/local/app/project_folder_path.post.ts +4 -4
- package/server/api/local/app/run_back.post.ts +5 -7
- package/server/api/local/app/run_viewer.post.ts +5 -7
- package/server/api/local/extensions/kill.post.ts +4 -3
- package/server/api/local/extensions/run.post.ts +7 -10
- package/server/api/local/extensions/upload.put.ts +44 -54
- package/server/api/microservice/app/get_is_app_ready.get.ts +4 -5
- package/server/api/microservice/app/set_app_base_url.post.ts +5 -6
- package/server/api/microservice/app/set_back_base_url.post.ts +5 -6
- package/server/api/microservice/app/set_is_app_ready.post.ts +5 -6
- package/server/api/microservice/app/set_viewer_base_url.post.ts +5 -6
- package/server/api/microservice/extensions/download.post.ts +5 -4
- package/server/api/serverless/run_cloud.post.ts +53 -11
- package/server/utils/app_config.ts +29 -22
- package/server/utils/cleanup.ts +60 -30
- package/server/utils/cloud.ts +9 -8
- package/server/utils/extension.ts +23 -9
- package/server/utils/microservices.ts +33 -24
- package/server/utils/path.ts +4 -4
- package/server/utils/scripts.ts +26 -23
- package/server/utils/server.ts +2 -2
- package/server/utils/server_config.ts +41 -27
- package/server/utils/stream.ts +6 -0
- package/server/utils/ws_client.ts +42 -8
- package/shared/scripts.ts +15 -10
- package/shared/utils/call_raw.ts +23 -16
- package/shared/utils/call_schema.ts +5 -8
- package/shared/utils/fetch_raw.ts +87 -47
- package/shared/utils/fetch_schema.ts +6 -9
- package/shared/utils/file.ts +8 -2
- package/shared/utils/response_handlers/load.ts +26 -11
- package/shared/utils/types.ts +9 -9
- package/shared/utils/validate_schema.ts +1 -1
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -276
- package/server/types/vendor.d.ts +0 -64
- package/server/utils/server_config.js +0 -43
- package/shared/utils/call_raw.js +0 -30
- package/shared/utils/fetch_raw.js +0 -40
- /package/{opengeodeweb_front_schemas.js → .build/opengeodeweb_front_schemas.js} +0 -0
- /package/{server → .build/server}/utils/server.js +0 -0
- /package/{shared → .build/shared}/app_mode.js +0 -0
- /package/{shared → .build/shared}/utils/parse_boolean.js +0 -0
- /package/{shared → .build/shared}/utils/types.js +0 -0
package/app/stores/menu.ts
CHANGED
|
@@ -48,6 +48,17 @@ interface MenuMetaData {
|
|
|
48
48
|
[key: string]: unknown;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
interface OpenMenuOptions {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly x: number | undefined;
|
|
54
|
+
readonly y: number | undefined;
|
|
55
|
+
readonly width: number;
|
|
56
|
+
readonly height: number;
|
|
57
|
+
readonly top: number;
|
|
58
|
+
readonly left: number;
|
|
59
|
+
readonly meta_data: MenuMetaData | undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
51
62
|
const PointSet_menu = [PointSetPointsOptions];
|
|
52
63
|
|
|
53
64
|
const EdgedCurve_menu = [EdgedCurvePointsOptions, EdgedCurveEdgesOptions];
|
|
@@ -146,10 +157,16 @@ export const useMenuStore = defineStore("menu", () => {
|
|
|
146
157
|
objectType: string | undefined,
|
|
147
158
|
geodeObject: string | undefined,
|
|
148
159
|
): MenuItems {
|
|
149
|
-
if (
|
|
160
|
+
if (
|
|
161
|
+
objectType === undefined ||
|
|
162
|
+
objectType === "" ||
|
|
163
|
+
geodeObject === undefined ||
|
|
164
|
+
geodeObject === "" ||
|
|
165
|
+
!menus.value[objectType]
|
|
166
|
+
) {
|
|
150
167
|
return [];
|
|
151
168
|
}
|
|
152
|
-
return menus.value[objectType]?.[geodeObject]
|
|
169
|
+
return menus.value[objectType]?.[geodeObject] ?? [];
|
|
153
170
|
}
|
|
154
171
|
|
|
155
172
|
function closeMenu(): void {
|
|
@@ -161,17 +178,9 @@ export const useMenuStore = defineStore("menu", () => {
|
|
|
161
178
|
display_menu.value = false;
|
|
162
179
|
}
|
|
163
180
|
|
|
164
|
-
|
|
165
|
-
id
|
|
166
|
-
|
|
167
|
-
y: number | undefined,
|
|
168
|
-
width: number,
|
|
169
|
-
height: number,
|
|
170
|
-
top: number,
|
|
171
|
-
left: number,
|
|
172
|
-
meta_data: MenuMetaData | undefined,
|
|
173
|
-
): Promise<void> {
|
|
174
|
-
await closeMenu();
|
|
181
|
+
function openMenu(options: OpenMenuOptions): void {
|
|
182
|
+
const { id, x, y, width, height, top, left, meta_data } = options;
|
|
183
|
+
closeMenu();
|
|
175
184
|
|
|
176
185
|
if (meta_data) {
|
|
177
186
|
const items = getMenuItems(meta_data.viewer_type, meta_data.geode_object_type);
|
|
@@ -181,7 +190,7 @@ export const useMenuStore = defineStore("menu", () => {
|
|
|
181
190
|
}
|
|
182
191
|
|
|
183
192
|
current_id.value = id;
|
|
184
|
-
current_meta_data.value = meta_data
|
|
193
|
+
current_meta_data.value = meta_data ?? {};
|
|
185
194
|
|
|
186
195
|
if (x !== undefined && y !== undefined) {
|
|
187
196
|
menuX.value = x;
|
package/app/stores/treeview.ts
CHANGED
|
@@ -55,6 +55,22 @@ function defaultOpenedViews(): OpenedView[] {
|
|
|
55
55
|
return [{ type: "object", id: "main", title: "Objects", scrollTop: 0, opened: [] }];
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
type ReadonlyOpenedView = Omit<OpenedView, "opened"> & {
|
|
59
|
+
readonly opened: readonly string[];
|
|
60
|
+
};
|
|
61
|
+
type ReadonlyTreeviewGroup = Omit<TreeviewGroup, "children"> & {
|
|
62
|
+
readonly children: readonly TreeviewChild[];
|
|
63
|
+
};
|
|
64
|
+
interface ReadonlyTreeviewSnapshot {
|
|
65
|
+
opened_views?: readonly ReadonlyOpenedView[];
|
|
66
|
+
panelWidth?: number;
|
|
67
|
+
additionalPanelWidth?: number;
|
|
68
|
+
rowHeights?: readonly number[];
|
|
69
|
+
selectionIds?: readonly string[];
|
|
70
|
+
selection?: readonly (string | { id: string })[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// oxlint-disable-next-line max-lines-per-function, max-statements
|
|
58
74
|
export const useTreeviewStore = defineStore("treeview", () => {
|
|
59
75
|
const items = ref<TreeviewGroup[]>([]);
|
|
60
76
|
const selection = ref<string[]>([]);
|
|
@@ -66,10 +82,12 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
66
82
|
const pendingSelectionIds = ref<string[]>([]);
|
|
67
83
|
const rowHeights = ref<number[]>([]);
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
// The database's table map is dynamically assembled at runtime (see internal/database/database.ts), so its exported type is a loose `{}`; cast it to the shape it actually has at runtime rather than widening every call site.
|
|
86
|
+
type DatabaseTables = Record<string, unknown>;
|
|
87
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- database's table map is dynamically typed at runtime; see comment above.
|
|
88
|
+
const typedDatabase = database as unknown as DatabaseTables;
|
|
89
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- database's table map is dynamically typed at runtime; see comment above.
|
|
90
|
+
const treeview_config_db = typedDatabase.treeview_config as Table<TreeviewConfigRecord, string>;
|
|
73
91
|
|
|
74
92
|
async function loadConfig(): Promise<void> {
|
|
75
93
|
try {
|
|
@@ -77,10 +95,10 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
77
95
|
if (config?.opened_views) {
|
|
78
96
|
opened_views.value = config.opened_views;
|
|
79
97
|
}
|
|
80
|
-
if (config?.panelWidth) {
|
|
98
|
+
if (config?.panelWidth !== undefined && config.panelWidth !== 0) {
|
|
81
99
|
panelWidth.value = config.panelWidth;
|
|
82
100
|
}
|
|
83
|
-
if (config?.additionalPanelWidth) {
|
|
101
|
+
if (config?.additionalPanelWidth !== undefined && config.additionalPanelWidth !== 0) {
|
|
84
102
|
additionalPanelWidth.value = config.additionalPanelWidth;
|
|
85
103
|
}
|
|
86
104
|
if (config?.selectionIds) {
|
|
@@ -90,21 +108,24 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
90
108
|
rowHeights.value = config.rowHeights;
|
|
91
109
|
}
|
|
92
110
|
} catch (error) {
|
|
111
|
+
// oxlint-disable-next-line no-console -- surfaces persistence failures during local development.
|
|
93
112
|
console.error("Failed to load treeview config:", error);
|
|
94
113
|
}
|
|
95
114
|
}
|
|
115
|
+
// oxlint-disable-next-line typescript/no-floating-promises -- loadConfig catches its own errors internally.
|
|
96
116
|
loadConfig();
|
|
97
117
|
|
|
98
118
|
watch(
|
|
99
119
|
[opened_views, panelWidth, additionalPanelWidth, selection, rowHeights],
|
|
100
120
|
() => {
|
|
101
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
102
|
-
const clean_opened_views = JSON.parse(JSON.stringify(opened_views.value));
|
|
103
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
104
|
-
const clean_selectionIds = JSON.parse(JSON.stringify(selection.value));
|
|
105
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
106
|
-
const clean_rowHeights = JSON.parse(JSON.stringify(rowHeights.value));
|
|
107
|
-
|
|
121
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone, no-unsafe-type-assertion -- JSON round-trip of a known-shape ref; result matches the source type.
|
|
122
|
+
const clean_opened_views = JSON.parse(JSON.stringify(opened_views.value)) as OpenedView[];
|
|
123
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone, no-unsafe-type-assertion -- JSON round-trip of a known-shape ref; result matches the source type.
|
|
124
|
+
const clean_selectionIds = JSON.parse(JSON.stringify(selection.value)) as string[];
|
|
125
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone, no-unsafe-type-assertion -- JSON round-trip of a known-shape ref; result matches the source type.
|
|
126
|
+
const clean_rowHeights = JSON.parse(JSON.stringify(rowHeights.value)) as number[];
|
|
127
|
+
|
|
128
|
+
// oxlint-disable-next-line typescript/no-floating-promises -- best-effort persistence; failures aren't actionable here.
|
|
108
129
|
treeview_config_db.put({
|
|
109
130
|
id: "main",
|
|
110
131
|
opened_views: clean_opened_views,
|
|
@@ -118,14 +139,14 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
118
139
|
);
|
|
119
140
|
|
|
120
141
|
function closeView(id: string): void {
|
|
121
|
-
opened_views.value = opened_views.value.filter((view) => view.id !== id);
|
|
142
|
+
opened_views.value = opened_views.value.filter((view: ReadonlyOpenedView) => view.id !== id);
|
|
122
143
|
}
|
|
123
144
|
|
|
124
|
-
watch(selection, (current, previous) => {
|
|
145
|
+
watch(selection, (current: readonly string[], previous: readonly string[]) => {
|
|
125
146
|
const { removed } = compareSelections(current, previous);
|
|
126
147
|
for (const id of removed) {
|
|
127
148
|
const index = opened_views.value.findIndex(
|
|
128
|
-
(view) => view.type === "component" && view.id === id,
|
|
149
|
+
(view: ReadonlyOpenedView) => view.type === "component" && view.id === id,
|
|
129
150
|
);
|
|
130
151
|
if (index !== -1) {
|
|
131
152
|
closeView(id);
|
|
@@ -134,7 +155,7 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
134
155
|
});
|
|
135
156
|
|
|
136
157
|
function toggleView(id: string): void {
|
|
137
|
-
const index = opened_views.value.findIndex((view) => view.id === id);
|
|
158
|
+
const index = opened_views.value.findIndex((view: ReadonlyOpenedView) => view.id === id);
|
|
138
159
|
if (index !== -1) {
|
|
139
160
|
closeView(id);
|
|
140
161
|
} else if (id === "main") {
|
|
@@ -170,7 +191,7 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
170
191
|
if (!found) {
|
|
171
192
|
items.value.push({ id: geodeObjectType, title: geodeObjectType, children: [child] });
|
|
172
193
|
const sort_options = { numeric: true, sensitivity: "base" as const };
|
|
173
|
-
items.value.sort((groupA, groupB) =>
|
|
194
|
+
items.value.sort((groupA: ReadonlyTreeviewGroup, groupB: ReadonlyTreeviewGroup) =>
|
|
174
195
|
groupA.title.localeCompare(groupB.title, undefined, sort_options),
|
|
175
196
|
);
|
|
176
197
|
}
|
|
@@ -199,12 +220,13 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
199
220
|
id: string,
|
|
200
221
|
title: string | undefined,
|
|
201
222
|
geodeObjectType: string,
|
|
202
|
-
viewType
|
|
203
|
-
) {
|
|
223
|
+
viewType = "model_components",
|
|
224
|
+
): void {
|
|
204
225
|
const viewId = `${id}_${viewType}`;
|
|
205
|
-
const index = opened_views.value.findIndex((view) => view.id === viewId);
|
|
226
|
+
const index = opened_views.value.findIndex((view: ReadonlyOpenedView) => view.id === viewId);
|
|
206
227
|
if (index !== -1) {
|
|
207
|
-
|
|
228
|
+
closeView(viewId);
|
|
229
|
+
return;
|
|
208
230
|
}
|
|
209
231
|
additionalPanelWidth.value = panelWidth.value;
|
|
210
232
|
opened_views.value.push({
|
|
@@ -212,7 +234,7 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
212
234
|
id: viewId,
|
|
213
235
|
modelId: id,
|
|
214
236
|
viewType,
|
|
215
|
-
title: title
|
|
237
|
+
title: title ?? id,
|
|
216
238
|
geode_object_type: geodeObjectType,
|
|
217
239
|
scrollTop: 0,
|
|
218
240
|
opened: [],
|
|
@@ -228,17 +250,19 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
228
250
|
}
|
|
229
251
|
}
|
|
230
252
|
|
|
231
|
-
function importStores(snapshot:
|
|
232
|
-
opened_views.value = snapshot?.opened_views
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
[]
|
|
253
|
+
function importStores(snapshot: ReadonlyTreeviewSnapshot | undefined): void {
|
|
254
|
+
opened_views.value = snapshot?.opened_views
|
|
255
|
+
? // oxlint-disable-next-line no-unsafe-type-assertion -- narrowing the readonly parameter view back to the mutable working type; these objects aren't actually frozen at runtime.
|
|
256
|
+
([...snapshot.opened_views] as OpenedView[])
|
|
257
|
+
: defaultOpenedViews();
|
|
258
|
+
panelWidth.value = snapshot?.panelWidth ?? PANEL_WIDTH;
|
|
259
|
+
additionalPanelWidth.value = snapshot?.additionalPanelWidth ?? PANEL_WIDTH;
|
|
260
|
+
rowHeights.value = snapshot?.rowHeights ? [...snapshot.rowHeights] : [];
|
|
261
|
+
pendingSelectionIds.value = snapshot?.selectionIds
|
|
262
|
+
? [...snapshot.selectionIds]
|
|
263
|
+
: (snapshot?.selection ?? []).map((selectionItem: string | { id: string }) =>
|
|
264
|
+
typeof selectionItem === "string" ? selectionItem : selectionItem.id,
|
|
265
|
+
);
|
|
242
266
|
}
|
|
243
267
|
|
|
244
268
|
function finalizeImportSelection(): void {
|
|
@@ -278,24 +302,28 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
278
302
|
}
|
|
279
303
|
|
|
280
304
|
function setScrollTop(viewId: string, scrollTop: number): void {
|
|
281
|
-
const view = opened_views.value.find(
|
|
305
|
+
const view = opened_views.value.find(
|
|
306
|
+
(openedView: ReadonlyOpenedView) => openedView.id === viewId,
|
|
307
|
+
);
|
|
282
308
|
if (view) {
|
|
283
309
|
view.scrollTop = scrollTop;
|
|
284
310
|
}
|
|
285
311
|
}
|
|
286
312
|
|
|
287
|
-
function setOpened(viewId: string, opened: string[]): void {
|
|
288
|
-
const view = opened_views.value.find(
|
|
313
|
+
function setOpened(viewId: string, opened: readonly string[]): void {
|
|
314
|
+
const view = opened_views.value.find(
|
|
315
|
+
(openedView: ReadonlyOpenedView) => openedView.id === viewId,
|
|
316
|
+
);
|
|
289
317
|
if (view) {
|
|
290
|
-
view.opened = opened;
|
|
318
|
+
view.opened = [...opened];
|
|
291
319
|
}
|
|
292
320
|
}
|
|
293
321
|
|
|
294
|
-
function setRowHeights(heights: number[]): void {
|
|
295
|
-
rowHeights.value = heights;
|
|
322
|
+
function setRowHeights(heights: readonly number[]): void {
|
|
323
|
+
rowHeights.value = [...heights];
|
|
296
324
|
}
|
|
297
325
|
|
|
298
|
-
function exportStores() {
|
|
326
|
+
function exportStores(): Omit<TreeviewConfigRecord, "id"> {
|
|
299
327
|
return {
|
|
300
328
|
opened_views: opened_views.value,
|
|
301
329
|
panelWidth: panelWidth.value,
|
|
@@ -317,7 +345,7 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
317
345
|
break;
|
|
318
346
|
}
|
|
319
347
|
}
|
|
320
|
-
const view = opened_views.value.find((openedView) => openedView.id === id);
|
|
348
|
+
const view = opened_views.value.find((openedView: ReadonlyOpenedView) => openedView.id === id);
|
|
321
349
|
if (view) {
|
|
322
350
|
view.title = newName;
|
|
323
351
|
}
|
|
@@ -351,3 +379,5 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
351
379
|
clear,
|
|
352
380
|
};
|
|
353
381
|
});
|
|
382
|
+
|
|
383
|
+
export type { TreeviewSnapshot };
|
package/app/stores/viewer.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { useInfraStore } from "@ogw_front/stores/infra";
|
|
|
18
18
|
import { viewer_call } from "@ogw_internal/utils/viewer_call";
|
|
19
19
|
|
|
20
20
|
import type { JsonRpcSchema, RequestHandlers } from "@ogw_shared/utils/types.js";
|
|
21
|
+
// oxlint-disable-next-line import/max-dependencies -- all imports above are required by this store.
|
|
21
22
|
import type { RpcClient } from "@ogw_shared/utils/call_raw.js";
|
|
22
23
|
|
|
23
24
|
interface PickedPoint {
|
|
@@ -35,6 +36,7 @@ export const useViewerStore = defineStore(
|
|
|
35
36
|
() => {
|
|
36
37
|
const infraStore = useInfraStore();
|
|
37
38
|
const default_local_port = ref("1234");
|
|
39
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- placeholder before the real client is set by ws_connect.
|
|
38
40
|
const client = ref<RpcClient>({} as RpcClient);
|
|
39
41
|
const config = ref<unknown>(undefined);
|
|
40
42
|
const picking_mode = ref(false);
|
|
@@ -56,21 +58,38 @@ export const useViewerStore = defineStore(
|
|
|
56
58
|
viewer_url += "/ws";
|
|
57
59
|
return viewer_url;
|
|
58
60
|
});
|
|
61
|
+
function start_request(): void {
|
|
62
|
+
request_counter.value += 1;
|
|
63
|
+
}
|
|
64
|
+
function stop_request(): void {
|
|
65
|
+
request_counter.value -= 1;
|
|
66
|
+
}
|
|
59
67
|
const is_busy = computed(() => request_counter.value > 0);
|
|
60
68
|
function toggle_picking_mode(value: boolean): void {
|
|
61
69
|
picking_mode.value = value;
|
|
62
70
|
}
|
|
63
|
-
function
|
|
71
|
+
// oxlint-disable-next-line unicorn/consistent-function-scoping
|
|
72
|
+
async function request(
|
|
64
73
|
{
|
|
65
74
|
schema,
|
|
66
75
|
params = {},
|
|
67
76
|
timeout = request_timeout,
|
|
68
|
-
}: {
|
|
77
|
+
}: {
|
|
78
|
+
schema: JsonRpcSchema;
|
|
79
|
+
params?: Record<string, unknown>;
|
|
80
|
+
timeout?: number;
|
|
81
|
+
},
|
|
69
82
|
callbacks: RequestHandlers = {},
|
|
70
83
|
): Promise<unknown> {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
const microservice = {
|
|
85
|
+
$id: "viewer",
|
|
86
|
+
client: client.value,
|
|
87
|
+
base_url: base_url.value,
|
|
88
|
+
start_request,
|
|
89
|
+
stop_request,
|
|
90
|
+
};
|
|
91
|
+
const result = await viewer_call(
|
|
92
|
+
microservice,
|
|
74
93
|
{
|
|
75
94
|
schema,
|
|
76
95
|
params,
|
|
@@ -85,6 +104,7 @@ export const useViewerStore = defineStore(
|
|
|
85
104
|
},
|
|
86
105
|
},
|
|
87
106
|
);
|
|
107
|
+
return result;
|
|
88
108
|
}
|
|
89
109
|
async function set_picked_point(x: number, y: number): Promise<void> {
|
|
90
110
|
const schema = opengeodeweb_viewer_schemas.opengeodeweb_viewer.viewer.get_point_position;
|
|
@@ -100,6 +120,7 @@ export const useViewerStore = defineStore(
|
|
|
100
120
|
x: world_x,
|
|
101
121
|
y: world_y,
|
|
102
122
|
z: world_z,
|
|
123
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- response shape is defined by the get_point_position schema.
|
|
103
124
|
} = response as { x: number; y: number; z: number };
|
|
104
125
|
picked_point.value = {
|
|
105
126
|
x: world_x,
|
|
@@ -107,23 +128,24 @@ export const useViewerStore = defineStore(
|
|
|
107
128
|
z: world_z,
|
|
108
129
|
};
|
|
109
130
|
}
|
|
110
|
-
function ws_connect() {
|
|
131
|
+
async function ws_connect(): Promise<void> {
|
|
111
132
|
if (status.value === Status.CONNECTED) {
|
|
112
|
-
return
|
|
133
|
+
return;
|
|
113
134
|
}
|
|
114
|
-
|
|
135
|
+
await navigator.locks.request("viewer.ws_connect", async () => {
|
|
115
136
|
if (status.value === Status.CONNECTED) {
|
|
116
137
|
return;
|
|
117
138
|
}
|
|
118
139
|
try {
|
|
119
|
-
console.log("VIEWER LOCK GRANTED !", lock);
|
|
120
140
|
status.value = Status.CONNECTING;
|
|
121
141
|
client.value = (await initWebSocketClient(base_url.value, client.value, {
|
|
122
142
|
onConnectionClose: () => {
|
|
123
143
|
status.value = Status.NOT_CONNECTED;
|
|
124
144
|
},
|
|
145
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- initWebSocketClient's return is not typed as RpcClient.
|
|
125
146
|
})) as unknown as RpcClient;
|
|
126
147
|
connectImageStream(client.value.getConnection().getSession());
|
|
148
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- endBusy is not part of the RpcClient type.
|
|
127
149
|
(client.value as unknown as { endBusy: () => void }).endBusy();
|
|
128
150
|
const schema = opengeodeweb_viewer_schemas.opengeodeweb_viewer.viewer.reset_visualization;
|
|
129
151
|
const timeout = undefined;
|
|
@@ -133,22 +155,12 @@ export const useViewerStore = defineStore(
|
|
|
133
155
|
});
|
|
134
156
|
status.value = Status.CONNECTED;
|
|
135
157
|
} catch (error) {
|
|
136
|
-
console.error("ws_connect error", error);
|
|
137
158
|
status.value = Status.NOT_CONNECTED;
|
|
138
159
|
throw error;
|
|
139
160
|
}
|
|
140
161
|
});
|
|
141
162
|
}
|
|
142
|
-
function
|
|
143
|
-
request_counter.value += 1;
|
|
144
|
-
}
|
|
145
|
-
function stop_request(): void {
|
|
146
|
-
request_counter.value -= 1;
|
|
147
|
-
}
|
|
148
|
-
function launch(args: { projectFolderPath?: string } = {}) {
|
|
149
|
-
console.log("[VIEWER] Launching viewer microservice...", {
|
|
150
|
-
args,
|
|
151
|
-
});
|
|
163
|
+
async function launch(args: Readonly<{ projectFolderPath?: string }> = {}): Promise<unknown> {
|
|
152
164
|
const appStore = useAppStore();
|
|
153
165
|
const { COMMAND_VIEWER, NUXT_ROOT_PATH } = useRuntimeConfig().public;
|
|
154
166
|
const schema = opengeodeweb_front_schemas.api.local.app.run_viewer;
|
|
@@ -157,41 +169,41 @@ export const useViewerStore = defineStore(
|
|
|
157
169
|
NUXT_ROOT_PATH,
|
|
158
170
|
args,
|
|
159
171
|
};
|
|
160
|
-
|
|
161
|
-
return appStore.request(
|
|
172
|
+
const result = await appStore.request(
|
|
162
173
|
{
|
|
163
174
|
schema,
|
|
164
175
|
params,
|
|
165
176
|
},
|
|
166
177
|
{
|
|
167
178
|
response_function: (response: unknown) => {
|
|
179
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- response shape is defined by the run_viewer schema.
|
|
168
180
|
const { port: viewerPort } = response as { port: string };
|
|
169
|
-
console.log(`[VIEWER] Viewer launched on port ${viewerPort}`);
|
|
170
181
|
default_local_port.value = viewerPort;
|
|
171
182
|
},
|
|
172
183
|
},
|
|
173
184
|
);
|
|
185
|
+
return result;
|
|
174
186
|
}
|
|
175
187
|
async function connect(): Promise<void> {
|
|
176
|
-
console.log("[VIEWER] Connecting to viewer microservice...");
|
|
177
188
|
await ws_connect();
|
|
178
|
-
console.log("[VIEWER] Viewer connected successfully");
|
|
179
189
|
}
|
|
180
|
-
function get_version(schema: JsonRpcSchema | undefined) {
|
|
190
|
+
async function get_version(schema: JsonRpcSchema | undefined): Promise<unknown> {
|
|
181
191
|
if (!schema) {
|
|
182
192
|
return undefined;
|
|
183
193
|
}
|
|
184
|
-
|
|
194
|
+
const result = await request(
|
|
185
195
|
{
|
|
186
196
|
schema,
|
|
187
197
|
},
|
|
188
198
|
{
|
|
189
199
|
response_function: (response: unknown) => {
|
|
200
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- response shape is defined by the version schema.
|
|
190
201
|
const { microservice_version } = response as { microservice_version: string };
|
|
191
202
|
version.value = microservice_version;
|
|
192
203
|
},
|
|
193
204
|
},
|
|
194
205
|
);
|
|
206
|
+
return result;
|
|
195
207
|
}
|
|
196
208
|
return {
|
|
197
209
|
default_local_port,
|
package/app/utils/attributes.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
interface AttributeRangeSource {
|
|
2
|
-
min_values?: number[];
|
|
3
|
-
max_values?: number[];
|
|
2
|
+
min_values?: readonly number[];
|
|
3
|
+
max_values?: readonly number[];
|
|
4
4
|
min_value?: number;
|
|
5
5
|
max_value?: number;
|
|
6
6
|
}
|
|
@@ -12,7 +12,7 @@ interface AttributeRange {
|
|
|
12
12
|
|
|
13
13
|
export function getAttributeRange(
|
|
14
14
|
currentAttribute: AttributeRangeSource | undefined | null,
|
|
15
|
-
compIndex
|
|
15
|
+
compIndex = 0,
|
|
16
16
|
): AttributeRange {
|
|
17
17
|
if (!currentAttribute) {
|
|
18
18
|
return { min: 0, max: 1 };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Bounds } from "@kitware/vtk.js/types";
|
|
2
2
|
import type vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
|
|
3
|
+
import type { vtkCamera } from "@kitware/vtk.js/Rendering/Core/Camera";
|
|
3
4
|
|
|
4
5
|
const AXIS_SCALE = 0.45;
|
|
5
6
|
const SIZE_RATIO = 0.1;
|
|
@@ -20,16 +21,15 @@ const DEFAULT_NORMALS = [NORMAL_X, NORMAL_Y, NORMAL_Z];
|
|
|
20
21
|
const RGB_MAX_VALUE = 255;
|
|
21
22
|
|
|
22
23
|
function getPlaneCssColor(index: number): string {
|
|
23
|
-
|
|
24
|
-
const rgb = PLANE_COLORS[index % PLANE_COLORS.length]!;
|
|
24
|
+
const rgb = PLANE_COLORS[index % PLANE_COLORS.length] ?? COLOR_BLUE;
|
|
25
25
|
return `rgb(${rgb.map((channel) => Math.round(channel * RGB_MAX_VALUE)).join(",")})`;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function hasPlaneChanged(
|
|
29
|
-
origin: number[],
|
|
30
|
-
normal: number[],
|
|
31
|
-
currentOrigin: number[] | undefined,
|
|
32
|
-
currentNormal: number[] | undefined,
|
|
29
|
+
origin: readonly number[],
|
|
30
|
+
normal: readonly number[],
|
|
31
|
+
currentOrigin: readonly number[] | undefined,
|
|
32
|
+
currentNormal: readonly number[] | undefined,
|
|
33
33
|
): boolean {
|
|
34
34
|
if (!currentOrigin) {
|
|
35
35
|
return true;
|
|
@@ -40,7 +40,27 @@ function hasPlaneChanged(
|
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
interface PlaneVisualState {
|
|
44
|
+
readonly plane: { readonly opacity: number; readonly color: readonly number[] };
|
|
45
|
+
readonly normal: { readonly opacity: number; readonly color: readonly number[] };
|
|
46
|
+
readonly origin: { readonly opacity: number; readonly color: readonly number[] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface PlaneStyle {
|
|
50
|
+
readonly active: PlaneVisualState;
|
|
51
|
+
readonly inactive: PlaneVisualState;
|
|
52
|
+
readonly static: {
|
|
53
|
+
readonly display2D: { readonly representation: number };
|
|
54
|
+
readonly outline: {
|
|
55
|
+
readonly color: readonly number[];
|
|
56
|
+
readonly opacity: number;
|
|
57
|
+
readonly representation: number;
|
|
58
|
+
readonly interpolation: number;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getPlaneStyle(rgb: readonly number[]): PlaneStyle {
|
|
44
64
|
return {
|
|
45
65
|
active: {
|
|
46
66
|
plane: { opacity: 1, color: rgb },
|
|
@@ -59,7 +79,7 @@ function getPlaneStyle(rgb: number[]) {
|
|
|
59
79
|
};
|
|
60
80
|
}
|
|
61
81
|
|
|
62
|
-
function computeSceneBounds(actors: vtkActor[]): Bounds {
|
|
82
|
+
function computeSceneBounds(actors: readonly vtkActor[]): Bounds {
|
|
63
83
|
let bounds: Bounds = [Infinity, -Infinity, Infinity, -Infinity, Infinity, -Infinity];
|
|
64
84
|
for (const actor of actors) {
|
|
65
85
|
const boundsOfActor = actor.getBounds();
|
|
@@ -76,12 +96,12 @@ function computeSceneBounds(actors: vtkActor[]): Bounds {
|
|
|
76
96
|
}
|
|
77
97
|
|
|
78
98
|
interface SceneBoundsInfo {
|
|
79
|
-
center: number[];
|
|
80
|
-
cubicBounds: number[];
|
|
99
|
+
readonly center: readonly number[];
|
|
100
|
+
readonly cubicBounds: readonly number[];
|
|
81
101
|
}
|
|
82
102
|
|
|
83
|
-
function computeSceneBoundsInfo(actors: vtkActor[]): SceneBoundsInfo {
|
|
84
|
-
if (
|
|
103
|
+
function computeSceneBoundsInfo(actors: readonly vtkActor[]): SceneBoundsInfo {
|
|
104
|
+
if (actors.length === 0) {
|
|
85
105
|
return { center: [0, 0, 0], cubicBounds: [-1, 1, -1, 1, -1, 1] };
|
|
86
106
|
}
|
|
87
107
|
const [xmin, xmax, ymin, ymax, zmin, zmax] = computeSceneBounds(actors);
|
|
@@ -92,13 +112,13 @@ function computeSceneBoundsInfo(actors: vtkActor[]): SceneBoundsInfo {
|
|
|
92
112
|
];
|
|
93
113
|
|
|
94
114
|
const maxActorExtent = Math.max(
|
|
95
|
-
...actors.map((actor) => {
|
|
115
|
+
...actors.map((actor: vtkActor) => {
|
|
96
116
|
const bounds = actor.getBounds();
|
|
97
117
|
return Math.max(bounds[1] - bounds[0], bounds[3] - bounds[2], bounds[5] - bounds[4]);
|
|
98
118
|
}),
|
|
99
119
|
);
|
|
100
120
|
const halfExtent = maxActorExtent / 2;
|
|
101
|
-
const [centerX, centerY, centerZ] = center
|
|
121
|
+
const [centerX = 0, centerY = 0, centerZ = 0] = center;
|
|
102
122
|
const cubicBounds = [
|
|
103
123
|
centerX - halfExtent,
|
|
104
124
|
centerX + halfExtent,
|
|
@@ -110,6 +130,79 @@ function computeSceneBoundsInfo(actors: vtkActor[]): SceneBoundsInfo {
|
|
|
110
130
|
return { center, cubicBounds };
|
|
111
131
|
}
|
|
112
132
|
|
|
133
|
+
interface ActorEntry {
|
|
134
|
+
readonly actor: vtkActor;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface MainCameraOptions {
|
|
138
|
+
readonly focal_point?: readonly number[];
|
|
139
|
+
readonly position?: readonly number[];
|
|
140
|
+
readonly view_up?: readonly number[];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function resolveActiveActors(
|
|
144
|
+
targetAllVisible: boolean,
|
|
145
|
+
allItems: readonly { readonly id: string }[],
|
|
146
|
+
selectedDatasetIds: readonly string[],
|
|
147
|
+
hybridDb: Record<string, ActorEntry | undefined>,
|
|
148
|
+
): vtkActor[] {
|
|
149
|
+
const targetIds = targetAllVisible
|
|
150
|
+
? allItems.map((item: { id: string }) => item.id)
|
|
151
|
+
: selectedDatasetIds;
|
|
152
|
+
const targeted = targetIds
|
|
153
|
+
.map((id) => hybridDb[id]?.actor)
|
|
154
|
+
.filter((actor: vtkActor | undefined): actor is vtkActor => actor !== undefined);
|
|
155
|
+
if (targeted.length > 0) {
|
|
156
|
+
return targeted;
|
|
157
|
+
}
|
|
158
|
+
return Object.values(hybridDb)
|
|
159
|
+
.filter((entry: ActorEntry | undefined): entry is ActorEntry => entry !== undefined)
|
|
160
|
+
.map((entry: ActorEntry) => entry.actor);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function computeNormalizedViewDirection(
|
|
164
|
+
focalPoint: readonly number[],
|
|
165
|
+
position: readonly number[],
|
|
166
|
+
): readonly number[] | undefined {
|
|
167
|
+
const dir = [
|
|
168
|
+
(position[0] ?? 0) - (focalPoint[0] ?? 0),
|
|
169
|
+
(position[1] ?? 0) - (focalPoint[1] ?? 0),
|
|
170
|
+
(position[2] ?? 0) - (focalPoint[2] ?? 0),
|
|
171
|
+
];
|
|
172
|
+
const dirLen = Math.hypot(...dir);
|
|
173
|
+
if (dirLen === 0) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
return dir.map((component) => component / dirLen);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Aligns the local clipping-plane preview camera onto the same viewing direction as the
|
|
180
|
+
// Main viewer camera, re-centered on the clipped scene's bounds.
|
|
181
|
+
function alignCameraToMainCamera(
|
|
182
|
+
camera: vtkCamera,
|
|
183
|
+
mainCam: MainCameraOptions,
|
|
184
|
+
center: readonly number[],
|
|
185
|
+
): void {
|
|
186
|
+
if (!mainCam.focal_point || !mainCam.position) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const normDir = computeNormalizedViewDirection(mainCam.focal_point, mainCam.position);
|
|
190
|
+
if (!normDir) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const distance = camera.getDistance();
|
|
194
|
+
camera.setFocalPoint(center[0] ?? 0, center[1] ?? 0, center[2] ?? 0);
|
|
195
|
+
camera.setPosition(
|
|
196
|
+
(center[0] ?? 0) + (normDir[0] ?? 0) * distance,
|
|
197
|
+
(center[1] ?? 0) + (normDir[1] ?? 0) * distance,
|
|
198
|
+
(center[2] ?? 0) + (normDir[2] ?? 0) * distance,
|
|
199
|
+
);
|
|
200
|
+
if (mainCam.view_up) {
|
|
201
|
+
const [viewUpX = 0, viewUpY = 0, viewUpZ = 0] = mainCam.view_up;
|
|
202
|
+
camera.setViewUp(viewUpX, viewUpY, viewUpZ);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
113
206
|
export {
|
|
114
207
|
AXIS_SCALE,
|
|
115
208
|
SIZE_RATIO,
|
|
@@ -122,4 +215,8 @@ export {
|
|
|
122
215
|
getPlaneStyle,
|
|
123
216
|
computeSceneBounds,
|
|
124
217
|
computeSceneBoundsInfo,
|
|
218
|
+
resolveActiveActors,
|
|
219
|
+
alignCameraToMainCamera,
|
|
125
220
|
};
|
|
221
|
+
|
|
222
|
+
export type { SceneBoundsInfo, MainCameraOptions };
|