@geode/opengeodeweb-front 10.34.0-rc.9 → 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
|
@@ -8,7 +8,7 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
|
8
8
|
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
|
|
9
9
|
|
|
10
10
|
// The four per-component-type style composables (Surface/Line/Block/Corner) each expose a different, large set of methods (color, visibility, per-attribute-kind getters/setters...). This module only cares about looking a handful of them up dynamically by name, so a precise structural type for componentStyleFunctions isn't worth modelling here; `any` keeps the dynamic dispatch table honest about that.
|
|
11
|
-
//
|
|
11
|
+
// oxlint-disable-next-line no-explicit-any
|
|
12
12
|
type ComponentStyleFunctions = Record<"Surface" | "Line" | "Block" | "Corner", any>;
|
|
13
13
|
|
|
14
14
|
interface ModelComponent {
|
|
@@ -16,8 +16,21 @@ interface ModelComponent {
|
|
|
16
16
|
type: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
async function callComponentStyleFunction(
|
|
20
|
+
// oxlint-disable-next-line no-explicit-any
|
|
21
|
+
target: any,
|
|
22
|
+
method: string,
|
|
23
|
+
...args: unknown[]
|
|
24
|
+
): Promise<unknown> {
|
|
25
|
+
// oxlint-disable-next-line no-unsafe-call, no-unsafe-member-access, no-unsafe-argument, no-unsafe-assignment -- ComponentStyleFunctions is deliberately dynamically typed; see comment above.
|
|
26
|
+
const result = await target[method](...args);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
const model_schemas = viewer_schemas.opengeodeweb_viewer.model;
|
|
20
|
-
async function getModelComponentsMap(
|
|
31
|
+
async function getModelComponentsMap(
|
|
32
|
+
modelId: string,
|
|
33
|
+
): Promise<{ allComponents: ModelComponent[]; componentsMap: Record<string, ModelComponent> }> {
|
|
21
34
|
const dataStore = useDataStore();
|
|
22
35
|
const results = await Promise.all(
|
|
23
36
|
MESH_COMPONENT_TYPES.map(async (type) => {
|
|
@@ -42,7 +55,7 @@ async function dispatchToComponentTypes(
|
|
|
42
55
|
action: string,
|
|
43
56
|
{ componentStyleFunctions }: { componentStyleFunctions: ComponentStyleFunctions },
|
|
44
57
|
...args: unknown[]
|
|
45
|
-
) {
|
|
58
|
+
): Promise<unknown[]> {
|
|
46
59
|
const { componentsMap } = await getModelComponentsMap(modelId);
|
|
47
60
|
const idsByComponent: { Block: string[]; Surface: string[]; Line: string[]; Corner: string[] } = {
|
|
48
61
|
Block: [],
|
|
@@ -52,15 +65,17 @@ async function dispatchToComponentTypes(
|
|
|
52
65
|
};
|
|
53
66
|
for (const id of componentIds) {
|
|
54
67
|
const type = componentsMap[id]?.type;
|
|
55
|
-
if (type && type in idsByComponent) {
|
|
56
|
-
(idsByComponent as Record<string, string[]>)[type]
|
|
68
|
+
if (type !== undefined && type in idsByComponent) {
|
|
69
|
+
(idsByComponent as Record<string, string[]>)[type]?.push(id);
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
const promises: Promise<unknown>[] = [];
|
|
60
73
|
if (action === "Visibility") {
|
|
61
74
|
if (idsByComponent.Block.length > 0) {
|
|
62
75
|
promises.push(
|
|
63
|
-
|
|
76
|
+
callComponentStyleFunction(
|
|
77
|
+
componentStyleFunctions.Block,
|
|
78
|
+
"setModelBlocksVisibility",
|
|
64
79
|
modelId,
|
|
65
80
|
idsByComponent.Block,
|
|
66
81
|
...args,
|
|
@@ -69,7 +84,9 @@ async function dispatchToComponentTypes(
|
|
|
69
84
|
}
|
|
70
85
|
if (idsByComponent.Surface.length > 0) {
|
|
71
86
|
promises.push(
|
|
72
|
-
|
|
87
|
+
callComponentStyleFunction(
|
|
88
|
+
componentStyleFunctions.Surface,
|
|
89
|
+
"setModelSurfacesVisibility",
|
|
73
90
|
modelId,
|
|
74
91
|
idsByComponent.Surface,
|
|
75
92
|
...args,
|
|
@@ -78,12 +95,20 @@ async function dispatchToComponentTypes(
|
|
|
78
95
|
}
|
|
79
96
|
if (idsByComponent.Line.length > 0) {
|
|
80
97
|
promises.push(
|
|
81
|
-
|
|
98
|
+
callComponentStyleFunction(
|
|
99
|
+
componentStyleFunctions.Line,
|
|
100
|
+
"setModelLinesVisibility",
|
|
101
|
+
modelId,
|
|
102
|
+
idsByComponent.Line,
|
|
103
|
+
...args,
|
|
104
|
+
),
|
|
82
105
|
);
|
|
83
106
|
}
|
|
84
107
|
if (idsByComponent.Corner.length > 0) {
|
|
85
108
|
promises.push(
|
|
86
|
-
|
|
109
|
+
callComponentStyleFunction(
|
|
110
|
+
componentStyleFunctions.Corner,
|
|
111
|
+
"setModelCornersVisibility",
|
|
87
112
|
modelId,
|
|
88
113
|
idsByComponent.Corner,
|
|
89
114
|
...args,
|
|
@@ -93,12 +118,20 @@ async function dispatchToComponentTypes(
|
|
|
93
118
|
} else if (action === "Color") {
|
|
94
119
|
if (idsByComponent.Block.length > 0) {
|
|
95
120
|
promises.push(
|
|
96
|
-
|
|
121
|
+
callComponentStyleFunction(
|
|
122
|
+
componentStyleFunctions.Block,
|
|
123
|
+
"setModelBlocksColor",
|
|
124
|
+
modelId,
|
|
125
|
+
idsByComponent.Block,
|
|
126
|
+
...args,
|
|
127
|
+
),
|
|
97
128
|
);
|
|
98
129
|
}
|
|
99
130
|
if (idsByComponent.Surface.length > 0) {
|
|
100
131
|
promises.push(
|
|
101
|
-
|
|
132
|
+
callComponentStyleFunction(
|
|
133
|
+
componentStyleFunctions.Surface,
|
|
134
|
+
"setModelSurfacesColor",
|
|
102
135
|
modelId,
|
|
103
136
|
idsByComponent.Surface,
|
|
104
137
|
...args,
|
|
@@ -107,12 +140,20 @@ async function dispatchToComponentTypes(
|
|
|
107
140
|
}
|
|
108
141
|
if (idsByComponent.Line.length > 0) {
|
|
109
142
|
promises.push(
|
|
110
|
-
|
|
143
|
+
callComponentStyleFunction(
|
|
144
|
+
componentStyleFunctions.Line,
|
|
145
|
+
"setModelLinesColor",
|
|
146
|
+
modelId,
|
|
147
|
+
idsByComponent.Line,
|
|
148
|
+
...args,
|
|
149
|
+
),
|
|
111
150
|
);
|
|
112
151
|
}
|
|
113
152
|
if (idsByComponent.Corner.length > 0) {
|
|
114
153
|
promises.push(
|
|
115
|
-
|
|
154
|
+
callComponentStyleFunction(
|
|
155
|
+
componentStyleFunctions.Corner,
|
|
156
|
+
"setModelCornersColor",
|
|
116
157
|
modelId,
|
|
117
158
|
idsByComponent.Corner,
|
|
118
159
|
...args,
|
|
@@ -122,8 +163,27 @@ async function dispatchToComponentTypes(
|
|
|
122
163
|
}
|
|
123
164
|
return Promise.all(promises);
|
|
124
165
|
}
|
|
166
|
+
interface UseModelVisibilityStyleReturn {
|
|
167
|
+
modelVisibility: (modelId: string) => boolean | undefined;
|
|
168
|
+
setModelVisibility: (modelId: string, visibility: boolean) => Promise<unknown>;
|
|
169
|
+
setModelComponentsVisibility: (
|
|
170
|
+
modelId: string,
|
|
171
|
+
componentIds: string[],
|
|
172
|
+
visibility: boolean,
|
|
173
|
+
) => Promise<unknown[]>;
|
|
174
|
+
setModelComponentTypeVisibility: (
|
|
175
|
+
modelId: string,
|
|
176
|
+
componentType: string,
|
|
177
|
+
visibility: boolean,
|
|
178
|
+
) => Promise<void>;
|
|
179
|
+
modelComponentVisibility: (modelId: string, componentId: string) => boolean;
|
|
180
|
+
modelComponentTypeVisibility: (modelId: string, componentType: string) => boolean;
|
|
181
|
+
}
|
|
182
|
+
|
|
125
183
|
// oxlint-disable-next-line max-lines-per-function
|
|
126
|
-
function useModelVisibilityStyle(
|
|
184
|
+
function useModelVisibilityStyle(
|
|
185
|
+
componentStyleFunctions: ComponentStyleFunctions,
|
|
186
|
+
): UseModelVisibilityStyleReturn {
|
|
127
187
|
const dataStore = useDataStore();
|
|
128
188
|
const dataStyleState = useDataStyleState();
|
|
129
189
|
const hybridViewerStore = useHybridViewerStore();
|
|
@@ -132,20 +192,20 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
|
|
|
132
192
|
function modelVisibility(modelId: string): boolean | undefined {
|
|
133
193
|
return dataStyleState.getStyle(modelId).visibility;
|
|
134
194
|
}
|
|
135
|
-
function setModelVisibility(modelId: string, visibility: boolean) {
|
|
195
|
+
async function setModelVisibility(modelId: string, visibility: boolean): Promise<unknown> {
|
|
136
196
|
const schema = model_schemas.visibility;
|
|
137
197
|
const params = {
|
|
138
198
|
id: modelId,
|
|
139
199
|
visibility,
|
|
140
200
|
};
|
|
141
|
-
|
|
201
|
+
const result = await viewerStore.request(
|
|
142
202
|
{
|
|
143
203
|
schema,
|
|
144
204
|
params,
|
|
145
205
|
},
|
|
146
206
|
{
|
|
147
207
|
response_function: async () => {
|
|
148
|
-
|
|
208
|
+
hybridViewerStore.setVisibility(modelId, visibility);
|
|
149
209
|
await dataStyleState.mutateStyle(modelId, {
|
|
150
210
|
visibility,
|
|
151
211
|
});
|
|
@@ -156,12 +216,13 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
|
|
|
156
216
|
},
|
|
157
217
|
},
|
|
158
218
|
);
|
|
219
|
+
return result;
|
|
159
220
|
}
|
|
160
221
|
async function setModelComponentTypeVisibility(
|
|
161
222
|
modelId: string,
|
|
162
223
|
componentType: string,
|
|
163
224
|
visibility: boolean,
|
|
164
|
-
) {
|
|
225
|
+
): Promise<void> {
|
|
165
226
|
await modelCommonStyle.mutateModelComponentTypeStyle(modelId, componentType, {
|
|
166
227
|
visibility,
|
|
167
228
|
});
|
|
@@ -183,7 +244,7 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
|
|
|
183
244
|
modelId: string,
|
|
184
245
|
componentIds: string[],
|
|
185
246
|
visibility: boolean,
|
|
186
|
-
) {
|
|
247
|
+
): Promise<unknown[]> {
|
|
187
248
|
const typeIds = componentIds.filter((id) => MESH_COMPONENT_TYPES.includes(id));
|
|
188
249
|
const individualIds = componentIds.filter((id) => !MESH_COMPONENT_TYPES.includes(id));
|
|
189
250
|
const promises: Promise<unknown>[] = [];
|
|
@@ -203,7 +264,8 @@ function useModelVisibilityStyle(componentStyleFunctions: ComponentStyleFunction
|
|
|
203
264
|
),
|
|
204
265
|
);
|
|
205
266
|
}
|
|
206
|
-
|
|
267
|
+
const results = await Promise.all(promises);
|
|
268
|
+
return results;
|
|
207
269
|
}
|
|
208
270
|
function modelComponentVisibility(modelId: string, componentId: string): boolean {
|
|
209
271
|
const selection = useModelSelection(modelId, dataStyleState);
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
2
|
-
// oxlint-disable eslint/sort-imports
|
|
3
1
|
import type {
|
|
4
2
|
ModelComponentStyle,
|
|
5
3
|
ModelComponentTypeStyle,
|
|
6
4
|
ObjectStyle,
|
|
7
5
|
StyleValues,
|
|
8
6
|
} from "./types";
|
|
9
|
-
import {
|
|
7
|
+
import type { Observable as RxObservable } from "rxjs";
|
|
8
|
+
import { getTable } from "@ogw_internal/database/database";
|
|
10
9
|
import { liveQuery } from "dexie";
|
|
11
10
|
import merge from "lodash/merge";
|
|
12
11
|
import { useObservable } from "@vueuse/rxjs";
|
|
13
|
-
import type { Ref } from "vue";
|
|
14
|
-
import type { Observable as RxObservable } from "rxjs";
|
|
15
12
|
|
|
16
13
|
interface SharedState {
|
|
17
14
|
styles: Ref<Record<string, ObjectStyle>>;
|
|
@@ -25,11 +22,14 @@ interface SharedState {
|
|
|
25
22
|
) => void;
|
|
26
23
|
bulkUpdateComponentStyleCache: (
|
|
27
24
|
modelId: string,
|
|
28
|
-
componentStyleUpdates: {
|
|
25
|
+
componentStyleUpdates: readonly {
|
|
26
|
+
readonly id_component: string;
|
|
27
|
+
readonly values: StyleValues;
|
|
28
|
+
}[],
|
|
29
29
|
) => void;
|
|
30
30
|
bulkUpdateComponentStylesCache: (
|
|
31
31
|
modelId: string,
|
|
32
|
-
componentIds: string[],
|
|
32
|
+
componentIds: readonly string[],
|
|
33
33
|
styleValues: StyleValues,
|
|
34
34
|
) => void;
|
|
35
35
|
updateModelComponentTypeStyleCache: (
|
|
@@ -48,32 +48,37 @@ function getSharedState(): SharedState {
|
|
|
48
48
|
return sharedState;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const dataStyleTable =
|
|
52
|
-
const modelComponentDataStyleTable =
|
|
53
|
-
const modelComponentTypeDataStyleTable =
|
|
51
|
+
const dataStyleTable = getTable<ObjectStyle>("data_style");
|
|
52
|
+
const modelComponentDataStyleTable = getTable<ModelComponentStyle>("model_component_datastyle");
|
|
53
|
+
const modelComponentTypeDataStyleTable = getTable<ModelComponentTypeStyle>(
|
|
54
|
+
"model_component_type_datastyle",
|
|
55
|
+
);
|
|
54
56
|
|
|
55
57
|
// Dexie's `liveQuery` returns Dexie's own `Observable` type, structurally distinct
|
|
56
58
|
// From rxjs's `Observable` that `useObservable` (from @vueuse/rxjs) expects, even
|
|
57
59
|
// Though they're interoperable at runtime (both are plain subscribe-based streams).
|
|
60
|
+
const dataStyleLiveQuery = liveQuery(async () => {
|
|
61
|
+
const objectStyles = await dataStyleTable.toArray();
|
|
62
|
+
const stylesByObjectId: Record<string, ObjectStyle> = {};
|
|
63
|
+
for (const objectStyle of objectStyles) {
|
|
64
|
+
stylesByObjectId[objectStyle.id] = objectStyle;
|
|
65
|
+
}
|
|
66
|
+
return stylesByObjectId;
|
|
67
|
+
});
|
|
68
|
+
|
|
58
69
|
const styles = useObservable<Record<string, ObjectStyle>, Record<string, ObjectStyle>>(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const stylesByObjectId: Record<string, ObjectStyle> = {};
|
|
62
|
-
for (const objectStyle of objectStyles) {
|
|
63
|
-
stylesByObjectId[objectStyle.id] = objectStyle;
|
|
64
|
-
}
|
|
65
|
-
return stylesByObjectId;
|
|
66
|
-
}) as unknown as RxObservable<Record<string, ObjectStyle>>,
|
|
70
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
71
|
+
dataStyleLiveQuery as unknown as RxObservable<Record<string, ObjectStyle>>,
|
|
67
72
|
{ initialValue: {} },
|
|
68
73
|
) as Ref<Record<string, ObjectStyle>>;
|
|
69
74
|
|
|
70
75
|
const modelComponentTypeStyles = ref<Record<string, ModelComponentTypeStyle>>({});
|
|
71
76
|
const componentStyles = ref<Record<string, ModelComponentStyle>>({});
|
|
72
77
|
|
|
73
|
-
async function loadFromDatabase() {
|
|
78
|
+
async function loadFromDatabase(): Promise<void> {
|
|
74
79
|
const [fetchedTypeStyles, fetchedComponentStyles] = await Promise.all([
|
|
75
|
-
modelComponentTypeDataStyleTable.toArray()
|
|
76
|
-
modelComponentDataStyleTable.toArray()
|
|
80
|
+
modelComponentTypeDataStyleTable.toArray(),
|
|
81
|
+
modelComponentDataStyleTable.toArray(),
|
|
77
82
|
]);
|
|
78
83
|
const typeStylesMap: Record<string, ModelComponentTypeStyle> = {};
|
|
79
84
|
for (const typeStyle of fetchedTypeStyles) {
|
|
@@ -90,44 +95,43 @@ function getSharedState(): SharedState {
|
|
|
90
95
|
componentStyles.value = componentStylesMap;
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
loadFromDatabase();
|
|
98
|
+
void loadFromDatabase();
|
|
94
99
|
|
|
95
100
|
function updateComponentStyleCache(
|
|
96
101
|
modelId: string,
|
|
97
102
|
componentId: string,
|
|
98
103
|
styleValues: StyleValues,
|
|
99
|
-
) {
|
|
104
|
+
): void {
|
|
100
105
|
const cacheKey = `${modelId}_${componentId}`;
|
|
101
106
|
const existingStyle = componentStyles.value[cacheKey];
|
|
102
|
-
if (existingStyle) {
|
|
103
|
-
merge(existingStyle, styleValues);
|
|
104
|
-
} else {
|
|
107
|
+
if (existingStyle === undefined) {
|
|
105
108
|
componentStyles.value[cacheKey] = merge(
|
|
106
109
|
{ id_model: modelId, id_component: componentId },
|
|
107
110
|
styleValues,
|
|
108
111
|
);
|
|
112
|
+
} else {
|
|
113
|
+
merge(existingStyle, styleValues);
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
function bulkUpdateComponentStyleCache(
|
|
113
118
|
modelId: string,
|
|
114
|
-
componentStyleUpdates: {
|
|
115
|
-
|
|
119
|
+
componentStyleUpdates: readonly {
|
|
120
|
+
readonly id_component: string;
|
|
121
|
+
readonly values: StyleValues;
|
|
122
|
+
}[],
|
|
123
|
+
): void {
|
|
116
124
|
const updatedComponentStyles = { ...componentStyles.value };
|
|
117
125
|
for (const { id_component: componentId, values: styleValues } of componentStyleUpdates) {
|
|
118
126
|
const cacheKey = `${modelId}_${componentId}`;
|
|
119
127
|
const existingStyle = updatedComponentStyles[cacheKey];
|
|
120
|
-
if (existingStyle) {
|
|
121
|
-
updatedComponentStyles[cacheKey] = merge(
|
|
122
|
-
{},
|
|
123
|
-
existingStyle,
|
|
124
|
-
styleValues,
|
|
125
|
-
) as ModelComponentStyle;
|
|
126
|
-
} else {
|
|
128
|
+
if (existingStyle === undefined) {
|
|
127
129
|
updatedComponentStyles[cacheKey] = merge(
|
|
128
130
|
{ id_model: modelId, id_component: componentId },
|
|
129
131
|
styleValues,
|
|
130
132
|
);
|
|
133
|
+
} else {
|
|
134
|
+
updatedComponentStyles[cacheKey] = merge({}, existingStyle, styleValues);
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
componentStyles.value = updatedComponentStyles;
|
|
@@ -135,24 +139,20 @@ function getSharedState(): SharedState {
|
|
|
135
139
|
|
|
136
140
|
function bulkUpdateComponentStylesCache(
|
|
137
141
|
modelId: string,
|
|
138
|
-
componentIds: string[],
|
|
142
|
+
componentIds: readonly string[],
|
|
139
143
|
styleValues: StyleValues,
|
|
140
|
-
) {
|
|
144
|
+
): void {
|
|
141
145
|
const updatedComponentStyles = { ...componentStyles.value };
|
|
142
146
|
for (const componentId of componentIds) {
|
|
143
147
|
const cacheKey = `${modelId}_${componentId}`;
|
|
144
148
|
const existingStyle = updatedComponentStyles[cacheKey];
|
|
145
|
-
if (existingStyle) {
|
|
146
|
-
updatedComponentStyles[cacheKey] = merge(
|
|
147
|
-
{},
|
|
148
|
-
existingStyle,
|
|
149
|
-
styleValues,
|
|
150
|
-
) as ModelComponentStyle;
|
|
151
|
-
} else {
|
|
149
|
+
if (existingStyle === undefined) {
|
|
152
150
|
updatedComponentStyles[cacheKey] = merge(
|
|
153
151
|
{ id_model: modelId, id_component: componentId },
|
|
154
152
|
styleValues,
|
|
155
153
|
);
|
|
154
|
+
} else {
|
|
155
|
+
updatedComponentStyles[cacheKey] = merge({}, existingStyle, styleValues);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
componentStyles.value = updatedComponentStyles;
|
|
@@ -162,18 +162,14 @@ function getSharedState(): SharedState {
|
|
|
162
162
|
modelId: string,
|
|
163
163
|
componentType: string,
|
|
164
164
|
styleValues: StyleValues,
|
|
165
|
-
) {
|
|
165
|
+
): void {
|
|
166
166
|
const cacheKey = `${modelId}_${componentType}`;
|
|
167
|
-
|
|
168
|
-
modelComponentTypeStyles.value[cacheKey] = { id_model: modelId, type: componentType };
|
|
169
|
-
}
|
|
167
|
+
modelComponentTypeStyles.value[cacheKey] ??= { id_model: modelId, type: componentType };
|
|
170
168
|
merge(modelComponentTypeStyles.value[cacheKey], styleValues);
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
function updateStyleCache(objectId: string, styleValues: StyleValues) {
|
|
174
|
-
|
|
175
|
-
styles.value[objectId] = { id: objectId };
|
|
176
|
-
}
|
|
171
|
+
function updateStyleCache(objectId: string, styleValues: StyleValues): void {
|
|
172
|
+
styles.value[objectId] ??= { id: objectId };
|
|
177
173
|
merge(styles.value[objectId], styleValues);
|
|
178
174
|
}
|
|
179
175
|
|
|
@@ -192,18 +188,30 @@ function getSharedState(): SharedState {
|
|
|
192
188
|
return sharedState;
|
|
193
189
|
}
|
|
194
190
|
|
|
191
|
+
interface DataStyleStateApi extends SharedState {
|
|
192
|
+
getStyle: (objectId: string) => ObjectStyle;
|
|
193
|
+
getComponentStyle: (modelId: string, componentId: string) => ModelComponentStyle;
|
|
194
|
+
getModelComponentTypeStyle: (modelId: string, componentType: string) => ModelComponentTypeStyle;
|
|
195
|
+
mutateStyle: (objectId: string, styleValues: StyleValues) => Promise<string>;
|
|
196
|
+
objectVisibility: ComputedRef<(objectId: string) => boolean | undefined>;
|
|
197
|
+
selectedObjects: ComputedRef<string[]>;
|
|
198
|
+
clear: () => Promise<void>;
|
|
199
|
+
}
|
|
200
|
+
|
|
195
201
|
// oxlint-disable-next-line max-lines-per-function
|
|
196
|
-
export function useDataStyleState() {
|
|
197
|
-
const dataStyleTable =
|
|
198
|
-
const modelComponentDataStyleTable =
|
|
199
|
-
const modelComponentTypeDataStyleTable =
|
|
202
|
+
export function useDataStyleState(): DataStyleStateApi {
|
|
203
|
+
const dataStyleTable = getTable<ObjectStyle>("data_style");
|
|
204
|
+
const modelComponentDataStyleTable = getTable<ModelComponentStyle>("model_component_datastyle");
|
|
205
|
+
const modelComponentTypeDataStyleTable = getTable<ModelComponentTypeStyle>(
|
|
206
|
+
"model_component_type_datastyle",
|
|
207
|
+
);
|
|
200
208
|
|
|
201
209
|
const state = getSharedState();
|
|
202
210
|
const { styles, modelComponentTypeStyles, componentStyles } = state;
|
|
203
211
|
|
|
204
212
|
const objectVisibility = computed(() => (objectId: string): boolean | undefined => {
|
|
205
213
|
const style = styles.value[objectId];
|
|
206
|
-
if (style) {
|
|
214
|
+
if (style !== undefined) {
|
|
207
215
|
return style.visibility;
|
|
208
216
|
}
|
|
209
217
|
return false;
|
|
@@ -220,19 +228,26 @@ export function useDataStyleState() {
|
|
|
220
228
|
});
|
|
221
229
|
|
|
222
230
|
function getStyle(objectId: string): ObjectStyle {
|
|
223
|
-
|
|
231
|
+
const style = styles.value[objectId];
|
|
232
|
+
if (style === undefined) {
|
|
233
|
+
return { id: objectId };
|
|
234
|
+
}
|
|
235
|
+
return { ...toRaw(style) };
|
|
224
236
|
}
|
|
225
237
|
|
|
226
|
-
function mutateStyle(objectId: string, styleValues: StyleValues) {
|
|
238
|
+
async function mutateStyle(objectId: string, styleValues: StyleValues): Promise<string> {
|
|
227
239
|
state.updateStyleCache(objectId, styleValues);
|
|
228
240
|
const currentStyle = getStyle(objectId);
|
|
229
241
|
merge(currentStyle, styleValues);
|
|
230
|
-
|
|
242
|
+
const savedId = await dataStyleTable.put(
|
|
243
|
+
structuredClone({ ...toRaw(currentStyle), id: objectId }),
|
|
244
|
+
);
|
|
245
|
+
return savedId;
|
|
231
246
|
}
|
|
232
247
|
|
|
233
248
|
function getComponentStyle(modelId: string, componentId: string): ModelComponentStyle {
|
|
234
249
|
const cacheKey = `${modelId}_${componentId}`;
|
|
235
|
-
return merge({ coloring: {} }, componentStyles.value[cacheKey])
|
|
250
|
+
return merge({ coloring: {} }, componentStyles.value[cacheKey]);
|
|
236
251
|
}
|
|
237
252
|
|
|
238
253
|
function getModelComponentTypeStyle(
|
|
@@ -240,10 +255,7 @@ export function useDataStyleState() {
|
|
|
240
255
|
componentType: string,
|
|
241
256
|
): ModelComponentTypeStyle {
|
|
242
257
|
const cacheKey = `${modelId}_${componentType}`;
|
|
243
|
-
return merge(
|
|
244
|
-
{ coloring: {} },
|
|
245
|
-
modelComponentTypeStyles.value[cacheKey],
|
|
246
|
-
) as ModelComponentTypeStyle;
|
|
258
|
+
return merge({ coloring: {} }, modelComponentTypeStyles.value[cacheKey]);
|
|
247
259
|
}
|
|
248
260
|
|
|
249
261
|
async function clear(): Promise<void> {
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
2
|
-
// oxlint-disable eslint/sort-imports
|
|
3
1
|
import { BACKGROUND_GREY_VALUE, RGB_MAX } from "./constants";
|
|
4
|
-
import {
|
|
5
|
-
import type { Ref } from "vue";
|
|
6
|
-
import type { HybridViewerStorePublic } from "./vtk_types";
|
|
2
|
+
import { useHybridViewerCore } from "./core";
|
|
7
3
|
|
|
8
4
|
const RGBA_CHANNELS = 4;
|
|
9
5
|
const SAMPLE_SIZE = 10;
|
|
@@ -25,7 +21,14 @@ interface BrightnessOptions {
|
|
|
25
21
|
offscreenCanvas: HTMLCanvasElement | undefined;
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
interface RelativeRect {
|
|
25
|
+
relX: number;
|
|
26
|
+
relY: number;
|
|
27
|
+
relW: number;
|
|
28
|
+
relH: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function mapRect(rect: Rect, latestImage: DrawableImage, canvasRect: DOMRect): RelativeRect {
|
|
29
32
|
const scaleX = latestImage.width / canvasRect.width;
|
|
30
33
|
const scaleY = latestImage.height / canvasRect.height;
|
|
31
34
|
return {
|
|
@@ -35,46 +38,61 @@ function mapRect(rect: Rect, latestImage: DrawableImage, canvasRect: DOMRect) {
|
|
|
35
38
|
relH: rect.height * scaleY,
|
|
36
39
|
};
|
|
37
40
|
}
|
|
41
|
+
|
|
42
|
+
function sampleMinBrightness(
|
|
43
|
+
ctx: CanvasRenderingContext2D,
|
|
44
|
+
image: DrawableImage,
|
|
45
|
+
relRect: RelativeRect,
|
|
46
|
+
): number {
|
|
47
|
+
ctx.drawImage(
|
|
48
|
+
image,
|
|
49
|
+
Math.max(0, relRect.relX),
|
|
50
|
+
Math.max(0, relRect.relY),
|
|
51
|
+
Math.min(image.width, relRect.relW),
|
|
52
|
+
Math.min(image.height, relRect.relH),
|
|
53
|
+
0,
|
|
54
|
+
0,
|
|
55
|
+
SAMPLE_SIZE,
|
|
56
|
+
SAMPLE_SIZE,
|
|
57
|
+
);
|
|
58
|
+
const { data } = ctx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
|
|
59
|
+
let minBrightness = 1;
|
|
60
|
+
for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
|
|
61
|
+
const brightness = ((data[i] ?? 0) + (data[i + 1] ?? 0) + (data[i + 2] ?? 0)) / (3 * RGB_MAX);
|
|
62
|
+
if (brightness < minBrightness) {
|
|
63
|
+
minBrightness = brightness;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return minBrightness;
|
|
67
|
+
}
|
|
68
|
+
|
|
38
69
|
function computeAverageBrightness(rect: Rect, options: BrightnessOptions): number {
|
|
39
70
|
const { latestImage, offscreenCtx, offscreenCanvas } = options;
|
|
40
|
-
const { genericRenderWindow } =
|
|
71
|
+
const { genericRenderWindow } = useHybridViewerCore();
|
|
41
72
|
if (!latestImage || !offscreenCtx || !offscreenCanvas || !genericRenderWindow.value) {
|
|
42
73
|
return BACKGROUND_GREY_VALUE / RGB_MAX;
|
|
43
74
|
}
|
|
44
|
-
|
|
45
|
-
|
|
75
|
+
// oxlint-disable-next-line no-unsafe-assignment -- vtk.js has no types for getApiSpecificRenderWindow(); narrowed below.
|
|
76
|
+
const webGLRenderWindow = genericRenderWindow.value.getApiSpecificRenderWindow();
|
|
77
|
+
// oxlint-disable-next-line no-unsafe-type-assertion -- trusted vtk.js OpenGL render window API boundary.
|
|
78
|
+
const apiSpecificRenderWindow = webGLRenderWindow as unknown as {
|
|
79
|
+
getCanvas: () => HTMLCanvasElement | null | undefined;
|
|
80
|
+
};
|
|
81
|
+
const canvas = apiSpecificRenderWindow.getCanvas();
|
|
82
|
+
if (canvas === undefined || canvas === null) {
|
|
46
83
|
return BACKGROUND_GREY_VALUE / RGB_MAX;
|
|
47
84
|
}
|
|
48
85
|
if (rect.width <= 0 || rect.height <= 0) {
|
|
49
86
|
return BACKGROUND_GREY_VALUE / RGB_MAX;
|
|
50
87
|
}
|
|
51
|
-
const
|
|
52
|
-
if (relW <= 0 || relH <= 0) {
|
|
88
|
+
const relRect = mapRect(rect, latestImage, canvas.getBoundingClientRect());
|
|
89
|
+
if (relRect.relW <= 0 || relRect.relH <= 0) {
|
|
53
90
|
return BACKGROUND_GREY_VALUE / RGB_MAX;
|
|
54
91
|
}
|
|
55
92
|
offscreenCanvas.width = SAMPLE_SIZE;
|
|
56
93
|
offscreenCanvas.height = SAMPLE_SIZE;
|
|
57
94
|
try {
|
|
58
|
-
offscreenCtx
|
|
59
|
-
latestImage,
|
|
60
|
-
Math.max(0, relX),
|
|
61
|
-
Math.max(0, relY),
|
|
62
|
-
Math.min(latestImage.width, relW),
|
|
63
|
-
Math.min(latestImage.height, relH),
|
|
64
|
-
0,
|
|
65
|
-
0,
|
|
66
|
-
SAMPLE_SIZE,
|
|
67
|
-
SAMPLE_SIZE,
|
|
68
|
-
);
|
|
69
|
-
const { data } = offscreenCtx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
|
|
70
|
-
let minBrightness = 1;
|
|
71
|
-
for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
|
|
72
|
-
const brightness = (data[i]! + data[i + 1]! + data[i + 2]!) / (3 * RGB_MAX);
|
|
73
|
-
if (brightness < minBrightness) {
|
|
74
|
-
minBrightness = brightness;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return minBrightness;
|
|
95
|
+
return sampleMinBrightness(offscreenCtx, latestImage, relRect);
|
|
78
96
|
} catch {
|
|
79
97
|
return BACKGROUND_GREY_VALUE / RGB_MAX;
|
|
80
98
|
}
|