volview 4.0.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/.browserslistrc +4 -0
- package/.editorconfig +6 -0
- package/.env +6 -0
- package/.eslintrc.js +109 -0
- package/.gitattributes +1 -0
- package/.github/workflows/checks.yml +16 -0
- package/.github/workflows/publish.yml +52 -0
- package/.prettierignore +5 -0
- package/CONTRIBUTING.md +29 -0
- package/LICENSE +202 -0
- package/README.md +44 -0
- package/babel.config.js +3 -0
- package/documentation/config.js +15 -0
- package/documentation/content/KWVolViewLogo.png +0 -0
- package/documentation/content/KWVolViewLogo.svg +35 -0
- package/documentation/content/VolViewLogo.png +0 -0
- package/documentation/content/VolViewLogo.svg +22 -0
- package/documentation/content/doc/index.md +64 -0
- package/documentation/content/doc/loading_data.md +30 -0
- package/documentation/content/doc/mouse_controls.md +34 -0
- package/documentation/content/doc/quick_start_guide.md +75 -0
- package/documentation/content/doc/rendering.md +27 -0
- package/documentation/content/doc/state_files.md +18 -0
- package/documentation/content/doc/toolbar.md +20 -0
- package/documentation/content/doc/welcome_screen.md +23 -0
- package/documentation/content/gallery/01-volview-welcome-notes.jpg +0 -0
- package/documentation/content/gallery/01-volview-welcome.jpg +0 -0
- package/documentation/content/gallery/02-volview-about.jpg +0 -0
- package/documentation/content/gallery/02-volview-notifications.jpg +0 -0
- package/documentation/content/gallery/02-volview-settings.jpg +0 -0
- package/documentation/content/gallery/03-volview-sample-datasets.jpg +0 -0
- package/documentation/content/gallery/04-volview-active-data.jpg +0 -0
- package/documentation/content/gallery/05-volview-select-data-to-delete.jpg +0 -0
- package/documentation/content/gallery/06-volview-corner-annotation.jpg +0 -0
- package/documentation/content/gallery/07-volview-layout-notes.jpg +0 -0
- package/documentation/content/gallery/07-volview-layout.jpg +0 -0
- package/documentation/content/gallery/09-volview-layout-3DPrimary.jpg +0 -0
- package/documentation/content/gallery/10-volview-wl-pan-zoom-notes.jpg +0 -0
- package/documentation/content/gallery/10-volview-wl-pan-zoom.jpg +0 -0
- package/documentation/content/gallery/11-volview-paint-notes.jpg +0 -0
- package/documentation/content/gallery/11-volview-paint.jpg +0 -0
- package/documentation/content/gallery/12-volview-paint-options.jpg +0 -0
- package/documentation/content/gallery/13-volview-crop-notes.jpg +0 -0
- package/documentation/content/gallery/13-volview-crop.jpg +0 -0
- package/documentation/content/gallery/14-volview-ruler.jpg +0 -0
- package/documentation/content/gallery/15-volview-crosshairs.jpg +0 -0
- package/documentation/content/gallery/16-volview-rendering.jpg +0 -0
- package/documentation/content/gallery/17-volview-colormap-notes.jpg +0 -0
- package/documentation/content/gallery/17-volview-colormap.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity-notes.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity2.jpg +0 -0
- package/documentation/content/gallery/18-volview-presets.jpg +0 -0
- package/documentation/content/gallery/19-volview-color.jpg +0 -0
- package/documentation/content/gallery/19-volview-color2.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera0.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera1.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera2.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera3.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid-final.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid0.0.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid0.5.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid1.0.jpg +0 -0
- package/documentation/content/gallery/LocalAmbientOcclusion.jpg +0 -0
- package/documentation/content/gallery/Notes.pptx +0 -0
- package/documentation/content/gallery/VolView-Overview.jpg +0 -0
- package/documentation/content/gallery/index.md +53 -0
- package/documentation/content/icon/favicon-16x16.png +0 -0
- package/documentation/content/icon/favicon-196x196.png +0 -0
- package/documentation/content/icon/favicon-32x32.png +0 -0
- package/documentation/content/icon/favicon-96x96.png +0 -0
- package/documentation/content/index.pug +43 -0
- package/documentation/content/logo.png +0 -0
- package/documentation/content/logo.svg +20 -0
- package/documentation/data/menu.yml +3 -0
- package/documentation/themes/navy/layout/partial/footer.swig +22 -0
- package/documentation/tpl/__en__ +31 -0
- package/documentation/tpl/__sidebar__ +11 -0
- package/package.json +96 -0
- package/patches/jsdom-global+3.0.2.patch +12 -0
- package/patches/vue-toastification+1.7.14.patch +41 -0
- package/patches/vuetify+2.6.10.patch +13 -0
- package/prettier.config.js +9 -0
- package/public/favicon.ico +0 -0
- package/public/global.css +20 -0
- package/public/index.html +28 -0
- package/public/pvm-sample.png +0 -0
- package/server/helper.py +147 -0
- package/server/host.js +134 -0
- package/server/serialize.js +111 -0
- package/server/serialize.py +203 -0
- package/server/server.py +84 -0
- package/server/test.py +17 -0
- package/src/assets/KitwareHeadAndNeck.jpg +0 -0
- package/src/assets/logo.png +0 -0
- package/src/assets/logo.svg +20 -0
- package/src/assets/samples/3DUS-Fetus.jpg +0 -0
- package/src/assets/samples/CTA-Head_and_Neck.jpg +0 -0
- package/src/assets/samples/MRA-Head_and_Neck.jpg +0 -0
- package/src/assets/samples/MRI-Cardiac.jpg +0 -0
- package/src/assets/samples/MRI-PROSTATEx.jpg +0 -0
- package/src/components/AboutBox.vue +157 -0
- package/src/components/AiModule.vue +60 -0
- package/src/components/AnnotationsModule.vue +37 -0
- package/src/components/App.vue +539 -0
- package/src/components/ColorFunctionSlider.vue +181 -0
- package/src/components/DataBrowser.vue +173 -0
- package/src/components/DragAndDrop.vue +107 -0
- package/src/components/GroupableItem.vue +30 -0
- package/src/components/ImageDataBrowser.vue +186 -0
- package/src/components/ImageListCard.vue +114 -0
- package/src/components/ItemGroup.vue +74 -0
- package/src/components/LabelmapList.vue +36 -0
- package/src/components/LayoutGrid.vue +96 -0
- package/src/components/MeasurementsList.vue +134 -0
- package/src/components/MessageCenter.vue +189 -0
- package/src/components/MessageItem.vue +83 -0
- package/src/components/MessageNotificationContent.vue +20 -0
- package/src/components/MessageNotifications.vue +84 -0
- package/src/components/ModelBrowser.vue +83 -0
- package/src/components/ModulePanel.vue +137 -0
- package/src/components/PaintControls.vue +174 -0
- package/src/components/PatientBrowser.vue +280 -0
- package/src/components/PatientStudyVolumeBrowser.vue +325 -0
- package/src/components/RenderingModule.vue +49 -0
- package/src/components/ResizableNavDrawer.vue +158 -0
- package/src/components/SampleDataBrowser.vue +198 -0
- package/src/components/SaveSession.vue +57 -0
- package/src/components/Settings.vue +35 -0
- package/src/components/SliceSlider.vue +182 -0
- package/src/components/SpleenModule.vue +101 -0
- package/src/components/ToolButton.vue +58 -0
- package/src/components/ToolStrip.vue +186 -0
- package/src/components/ViewOverlayGrid.vue +84 -0
- package/src/components/VolumePresets.vue +165 -0
- package/src/components/VolumeProperties.vue +171 -0
- package/src/components/VolumeRendering.vue +365 -0
- package/src/components/VtkThreeView.vue +512 -0
- package/src/components/VtkTwoView.vue +665 -0
- package/src/components/__tests__/ResizableNavDrawer.spec.js +32 -0
- package/src/components/__tests__/ToolButton.spec.js +46 -0
- package/src/components/icons/KitwareLogoIcon.vue +54 -0
- package/src/components/icons/VolViewFullLogo.vue +139 -0
- package/src/components/icons/VolViewLogo.vue +78 -0
- package/src/components/styles/utils.css +16 -0
- package/src/components/styles/vtk-view.css +116 -0
- package/src/components/tools/CropTool.vue +61 -0
- package/src/components/tools/CrosshairsTool.vue +93 -0
- package/src/components/tools/MouseManipulatorTool.vue +108 -0
- package/src/components/tools/PaintTool.vue +54 -0
- package/src/components/tools/PanTool.vue +35 -0
- package/src/components/tools/RulerTool.vue +202 -0
- package/src/components/tools/SliceScrollTool.vue +123 -0
- package/src/components/tools/WindowLevelTool.vue +191 -0
- package/src/components/tools/ZoomTool.vue +35 -0
- package/src/components/tools/crop/Crop2D.vue +367 -0
- package/src/components/tools/crop/Crop2DLineHandle.vue +103 -0
- package/src/components/tools/crop/Crop3D.vue +192 -0
- package/src/components/tools/crop/CropControls.vue +38 -0
- package/src/components/tools/crop/types.ts +12 -0
- package/src/components/tools/crosshairs/CrosshairSVG2D.vue +125 -0
- package/src/components/tools/crosshairs/CrosshairsWidget2D.vue +100 -0
- package/src/components/tools/paint/PaintWidget2D.vue +192 -0
- package/src/components/tools/ruler/RulerSVG2D.vue +181 -0
- package/src/components/tools/ruler/RulerWidget2D.vue +154 -0
- package/src/composables/__tests__/useDoubleRecord.spec.ts +57 -0
- package/src/composables/__tests__/useOrientationLabels.spec.ts +29 -0
- package/src/composables/isViewAnimating.ts +25 -0
- package/src/composables/manageVTKSubscription.ts +6 -0
- package/src/composables/onProxyManagerEvent.ts +50 -0
- package/src/composables/proxyManager.ts +13 -0
- package/src/composables/sync/__tests__/createPrimitiveSyncContext.spec.ts +41 -0
- package/src/composables/sync/__tests__/useWindowingSync.spec.ts +51 -0
- package/src/composables/sync/createPrimitiveSyncContext.ts +83 -0
- package/src/composables/sync/useWindowingSync.ts +48 -0
- package/src/composables/useAppLoadingNotifications.ts +73 -0
- package/src/composables/useCameraOrientation.ts +34 -0
- package/src/composables/useCurrentImage.ts +74 -0
- package/src/composables/useCurrentSlice.ts +43 -0
- package/src/composables/useDoubleRecord.ts +77 -0
- package/src/composables/useEventListener.ts +26 -0
- package/src/composables/useGlobalErrorHook.ts +18 -0
- package/src/composables/useMultiSelection.ts +29 -0
- package/src/composables/useOrientationLabels.ts +62 -0
- package/src/composables/usePanels.ts +42 -0
- package/src/composables/usePersistCameraConfig.ts +138 -0
- package/src/composables/useResizeObserver.ts +37 -0
- package/src/composables/useResizeToFit.ts +50 -0
- package/src/composables/useSceneBuilder.ts +96 -0
- package/src/composables/useToast.js +11 -0
- package/src/composables/useVTKCallback.ts +33 -0
- package/src/composables/useVTKWorldToDisplay.ts +141 -0
- package/src/composables/useViewProxy.ts +87 -0
- package/src/composables/useVolumeThumbnailing.ts +173 -0
- package/src/composables/useWebGLWatchdog.ts +32 -0
- package/src/composables/useWidgetManager.ts +41 -0
- package/src/config.ts +182 -0
- package/src/constants.ts +38 -0
- package/src/core/id.ts +18 -0
- package/src/core/provider.ts +31 -0
- package/src/core/proxies.ts +90 -0
- package/src/core/thumbnailers/__tests__/vtk-image.spec.ts +58 -0
- package/src/core/thumbnailers/index.ts +5 -0
- package/src/core/thumbnailers/volume-thumbnailer.ts +130 -0
- package/src/core/thumbnailers/vtk-image.ts +142 -0
- package/src/core/tools/__tests__/paint.spec.ts +101 -0
- package/src/core/tools/__tests__/ruler.spec.ts +73 -0
- package/src/core/tools/paint/brush.ts +20 -0
- package/src/core/tools/paint/ellipse-brush.ts +96 -0
- package/src/core/tools/paint/index.ts +141 -0
- package/src/core/tools/ruler.ts +149 -0
- package/src/global.d.ts +24 -0
- package/src/io/__tests__/io.spec.ts +26 -0
- package/src/io/dicom.ts +187 -0
- package/src/io/index.ts +11 -0
- package/src/io/io.ts +157 -0
- package/src/io/itk/itkConfig.js +8 -0
- package/src/io/itk-dicom/dicom.cpp +327 -0
- package/src/io/itk-dicom/web-build/dicom.js +16 -0
- package/src/io/itk-dicom/web-build/dicom.umd.js +21 -0
- package/src/io/itk-dicom/web-build/dicom.umd.wasm +0 -0
- package/src/io/itk-dicom/web-build/dicom.wasm +0 -0
- package/src/io/manifest.ts +30 -0
- package/src/io/readers.ts +36 -0
- package/src/io/state-file/index.ts +170 -0
- package/src/io/state-file/schema.ts +277 -0
- package/src/io/state-file/utils.ts +33 -0
- package/src/io/types.ts +4 -0
- package/src/io/vtk/async.reader.worker.ts +50 -0
- package/src/io/vtk/async.ts +58 -0
- package/src/io/vtk/async.writer.worker.ts +46 -0
- package/src/io/vtk/common.ts +30 -0
- package/src/io/zip.ts +31 -0
- package/src/main.js +66 -0
- package/src/main.ts +1 -0
- package/src/plugins/vuetify.js +25 -0
- package/src/shims-itk.d.ts +67 -0
- package/src/shims-misc.d.ts +4 -0
- package/src/shims-tsx.d.ts +13 -0
- package/src/shims-vtk.d.ts +1042 -0
- package/src/shims-vue.d.ts +5 -0
- package/src/store/__tests__/datasets.spec.ts +75 -0
- package/src/store/__tests__/messages.spec.ts +74 -0
- package/src/store/__tests__/rulers.spec.ts +77 -0
- package/src/store/__tests__/view-configs.spec.ts +37 -0
- package/src/store/datasets-dicom.ts +398 -0
- package/src/store/datasets-files.ts +35 -0
- package/src/store/datasets-images.ts +118 -0
- package/src/store/datasets-labelmaps.ts +136 -0
- package/src/store/datasets-models.ts +25 -0
- package/src/store/datasets.ts +341 -0
- package/src/store/messages.ts +144 -0
- package/src/store/tools/crop.ts +136 -0
- package/src/store/tools/crosshairs.ts +131 -0
- package/src/store/tools/index.ts +95 -0
- package/src/store/tools/paint.ts +191 -0
- package/src/store/tools/rulers.ts +305 -0
- package/src/store/tools/types.ts +54 -0
- package/src/store/view-configs/camera.ts +51 -0
- package/src/store/view-configs/common.ts +61 -0
- package/src/store/view-configs/slicing.ts +86 -0
- package/src/store/view-configs/types.ts +39 -0
- package/src/store/view-configs/volume-coloring.ts +193 -0
- package/src/store/view-configs/windowing.ts +69 -0
- package/src/store/view-configs.ts +78 -0
- package/src/store/views.ts +130 -0
- package/src/types/index.ts +16 -0
- package/src/types/layout.ts +10 -0
- package/src/types/lps.ts +40 -0
- package/src/types/views.ts +65 -0
- package/src/types/vtk-types.ts +29 -0
- package/src/utils/__tests__/lps.spec.ts +102 -0
- package/src/utils/color.ts +23 -0
- package/src/utils/errors.js +3 -0
- package/src/utils/fetch.ts +101 -0
- package/src/utils/hacks.ts +14 -0
- package/src/utils/index.ts +83 -0
- package/src/utils/lps.ts +129 -0
- package/src/utils/manipulators.ts +35 -0
- package/src/utils/promise-worker.ts +45 -0
- package/src/utils/vtk-helpers.ts +215 -0
- package/src/utils/workerHandler.js +42 -0
- package/src/vtk/ColorMaps.ts +72 -0
- package/src/vtk/CrosshairsWidget/behavior.ts +112 -0
- package/src/vtk/CrosshairsWidget/index.d.ts +22 -0
- package/src/vtk/CrosshairsWidget/index.js +73 -0
- package/src/vtk/CrosshairsWidget/state.ts +51 -0
- package/src/vtk/IJKSliceRepresentationProxy/index.d.ts +9 -0
- package/src/vtk/IJKSliceRepresentationProxy/index.js +59 -0
- package/src/vtk/LPSView2DProxy/index.d.ts +18 -0
- package/src/vtk/LPSView2DProxy/index.js +89 -0
- package/src/vtk/LPSView3DProxy/index.d.ts +16 -0
- package/src/vtk/LPSView3DProxy/index.js +78 -0
- package/src/vtk/LabelMap/index.d.ts +16 -0
- package/src/vtk/LabelMap/index.js +49 -0
- package/src/vtk/LabelMapSliceRepProxy/index.d.ts +6 -0
- package/src/vtk/LabelMapSliceRepProxy/index.js +104 -0
- package/src/vtk/MedicalColorPresets.json +1448 -0
- package/src/vtk/PaintBrushContextRepresentation/index.js +191 -0
- package/src/vtk/PaintWidget/behavior.ts +101 -0
- package/src/vtk/PaintWidget/index.d.ts +28 -0
- package/src/vtk/PaintWidget/index.js +56 -0
- package/src/vtk/PaintWidget/state.ts +41 -0
- package/src/vtk/PiecewiseWidget/index.js +203 -0
- package/src/vtk/RulerWidget/behavior.ts +185 -0
- package/src/vtk/RulerWidget/index.d.ts +25 -0
- package/src/vtk/RulerWidget/index.js +79 -0
- package/src/vtk/RulerWidget/state.ts +63 -0
- package/src/vtk/TreJsonConverter/index.js +150 -0
- package/src/vtk/proxy.js +66 -0
- package/src/vtk/proxyUtils.js +16 -0
- package/src/vtk/webvr-empty.js +1 -0
- package/tests/testUtils.js +12 -0
- package/tsconfig.json +46 -0
- package/vue.config.js +86 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import vtkPiecewiseFunctionProxy from '@kitware/vtk.js/Proxy/Core/PiecewiseFunctionProxy';
|
|
2
|
+
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps';
|
|
3
|
+
import vtkRenderer from '@kitware/vtk.js/Rendering/Core/Renderer';
|
|
4
|
+
import vtkOpenGLRenderWindow from '@kitware/vtk.js/Rendering/OpenGL/RenderWindow';
|
|
5
|
+
import { Vector2, Vector3 } from '@kitware/vtk.js/types';
|
|
6
|
+
import { intersectDisplayWithPlane } from '@kitware/vtk.js/Widgets/Manipulators/PlaneManipulator';
|
|
7
|
+
import { OpacityFunction } from '../types/views';
|
|
8
|
+
|
|
9
|
+
export function computeWorldToDisplay(
|
|
10
|
+
xyz: Vector3,
|
|
11
|
+
renderer: vtkRenderer
|
|
12
|
+
): Vector2 | null {
|
|
13
|
+
const view = renderer.getRenderWindow()?.getViews()?.[0];
|
|
14
|
+
if (view) {
|
|
15
|
+
const [x, y, z] = xyz;
|
|
16
|
+
return view.worldToDisplay(x, y, z, renderer);
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function computeDisplayToWorld(
|
|
22
|
+
xy: Vector2,
|
|
23
|
+
renderer: vtkRenderer
|
|
24
|
+
): Vector3 | null {
|
|
25
|
+
const view = renderer.getRenderWindow()?.getViews()?.[0];
|
|
26
|
+
if (view) {
|
|
27
|
+
const [x, y] = xy;
|
|
28
|
+
return view.displayToWorld(x, y, 0, renderer);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function normalizeMouseEventPosition(
|
|
34
|
+
ev: MouseEvent,
|
|
35
|
+
view: vtkOpenGLRenderWindow
|
|
36
|
+
) {
|
|
37
|
+
// TODO fix typing in vtk.js
|
|
38
|
+
const canvas = (view as any).getCanvas() as HTMLCanvasElement | null;
|
|
39
|
+
if (!canvas) return null;
|
|
40
|
+
|
|
41
|
+
const bounds = canvas.getBoundingClientRect();
|
|
42
|
+
const scaleX = canvas.width / bounds.width;
|
|
43
|
+
const scaleY = canvas.height / bounds.height;
|
|
44
|
+
return [
|
|
45
|
+
scaleX * (ev.clientX - bounds.left),
|
|
46
|
+
scaleY * (bounds.height - ev.clientY + bounds.top),
|
|
47
|
+
] as Vector2;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function intersectMouseEventWithPlane(
|
|
51
|
+
ev: MouseEvent,
|
|
52
|
+
renderer: vtkRenderer,
|
|
53
|
+
origin: Vector3,
|
|
54
|
+
normal: Vector3
|
|
55
|
+
) {
|
|
56
|
+
const view = renderer
|
|
57
|
+
.getRenderWindow()
|
|
58
|
+
?.getViews()[0] as vtkOpenGLRenderWindow;
|
|
59
|
+
if (!view) return null;
|
|
60
|
+
|
|
61
|
+
const position = normalizeMouseEventPosition(ev, view);
|
|
62
|
+
if (!position) return null;
|
|
63
|
+
|
|
64
|
+
return intersectDisplayWithPlane(
|
|
65
|
+
position[0],
|
|
66
|
+
position[1],
|
|
67
|
+
origin,
|
|
68
|
+
normal,
|
|
69
|
+
renderer,
|
|
70
|
+
view
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Converts world coordinates to SVG-friendly coordinates.
|
|
76
|
+
*
|
|
77
|
+
* Assumes that the SVG layer is the same size as the renderer.
|
|
78
|
+
* TODO verify this is the case.
|
|
79
|
+
*/
|
|
80
|
+
export function worldToSVG(xyz: Vector3, renderer: vtkRenderer) {
|
|
81
|
+
const coords = computeWorldToDisplay(xyz, renderer);
|
|
82
|
+
const view = renderer.getRenderWindow()?.getViews()?.[0];
|
|
83
|
+
if (coords && view) {
|
|
84
|
+
const [, height] = view.getViewportSize(renderer);
|
|
85
|
+
// convert from canvas space to svg space
|
|
86
|
+
return [
|
|
87
|
+
coords[0] / devicePixelRatio,
|
|
88
|
+
(height - coords[1]) / devicePixelRatio,
|
|
89
|
+
] as Vector2;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Gets the CSS coordinates for a vtk.js mouse event.
|
|
96
|
+
*/
|
|
97
|
+
export function getCSSCoordinatesFromEvent(eventData: any) {
|
|
98
|
+
const { pokedRenderer }: { pokedRenderer: vtkRenderer } = eventData;
|
|
99
|
+
const view = pokedRenderer?.getRenderWindow()?.getViews()?.[0] as
|
|
100
|
+
| vtkOpenGLRenderWindow
|
|
101
|
+
| undefined;
|
|
102
|
+
const bbox = view?.getContainer()?.getBoundingClientRect();
|
|
103
|
+
|
|
104
|
+
if (!('position' in eventData) || !bbox) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [
|
|
109
|
+
bbox.left + eventData.position.x / devicePixelRatio,
|
|
110
|
+
bbox.top + bbox.height - eventData.position.y / devicePixelRatio,
|
|
111
|
+
] as Vector2;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Shifts the opacity points from a preset.
|
|
116
|
+
*/
|
|
117
|
+
export function getShiftedOpacityFromPreset(
|
|
118
|
+
presetName: string,
|
|
119
|
+
effectiveRange: [number, number],
|
|
120
|
+
shift: number
|
|
121
|
+
) {
|
|
122
|
+
const preset = vtkColorMaps.getPresetByName(presetName);
|
|
123
|
+
if (preset.OpacityPoints) {
|
|
124
|
+
const OpacityPoints = preset.OpacityPoints as number[];
|
|
125
|
+
const points = [];
|
|
126
|
+
for (let i = 0; i < OpacityPoints.length; i += 2) {
|
|
127
|
+
points.push([OpacityPoints[i], OpacityPoints[i + 1]]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const [xmin, xmax] = effectiveRange;
|
|
131
|
+
const width = xmax - xmin;
|
|
132
|
+
return points.map(([x, y]) => [(x - xmin) / width + shift, y]);
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Retrieves an OpacityFunction from a preset.
|
|
139
|
+
*/
|
|
140
|
+
export function getOpacityFunctionFromPreset(
|
|
141
|
+
presetName: string
|
|
142
|
+
): Partial<OpacityFunction> {
|
|
143
|
+
const preset = vtkColorMaps.getPresetByName(presetName);
|
|
144
|
+
|
|
145
|
+
if (preset.OpacityPoints) {
|
|
146
|
+
return {
|
|
147
|
+
mode: vtkPiecewiseFunctionProxy.Mode.Points,
|
|
148
|
+
preset: presetName,
|
|
149
|
+
shift: 0,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
mode: vtkPiecewiseFunctionProxy.Mode.Gaussians,
|
|
154
|
+
// deep-copy necessary
|
|
155
|
+
gaussians: JSON.parse(
|
|
156
|
+
JSON.stringify(vtkPiecewiseFunctionProxy.Defaults.Gaussians)
|
|
157
|
+
),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Inflate an axis bounds defined as [min, max] by some delta.
|
|
163
|
+
*
|
|
164
|
+
* @param bounds Must be [number, number]. (Typed number[] for convenience.)
|
|
165
|
+
* @param delta
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
export function inflateAxisBounds(bounds: number[], delta: number) {
|
|
169
|
+
return [bounds[0] + delta, bounds[1] + delta];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Retrieves the color function range, if any.
|
|
174
|
+
*
|
|
175
|
+
* Will only return the color function range if the preset
|
|
176
|
+
* has AbsoluteRange specified as true. For medical presets,
|
|
177
|
+
* the range is defined by the transfer function point range,
|
|
178
|
+
* rather than the dataset data range.
|
|
179
|
+
* @param presetName
|
|
180
|
+
* @returns
|
|
181
|
+
*/
|
|
182
|
+
export function getColorFunctionRangeFromPreset(
|
|
183
|
+
presetName: string
|
|
184
|
+
): [number, number] | null {
|
|
185
|
+
const preset = vtkColorMaps.getPresetByName(presetName);
|
|
186
|
+
if (!preset) return null;
|
|
187
|
+
|
|
188
|
+
const { AbsoluteRange, RGBPoints } = preset;
|
|
189
|
+
if (AbsoluteRange && RGBPoints) {
|
|
190
|
+
let min = Infinity;
|
|
191
|
+
let max = -Infinity;
|
|
192
|
+
for (let i = 0; i < RGBPoints.length; i += 4) {
|
|
193
|
+
min = Math.min(min, RGBPoints[i]);
|
|
194
|
+
max = Math.max(max, RGBPoints[i]);
|
|
195
|
+
}
|
|
196
|
+
return [min, max];
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Retrieves the effective opacity mapping range, if any.
|
|
203
|
+
*
|
|
204
|
+
* Presets may specify an effective range for the scalar opacity
|
|
205
|
+
* mapping range.
|
|
206
|
+
* @param presetName
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
209
|
+
export function getOpacityRangeFromPreset(presetName: string) {
|
|
210
|
+
const preset = vtkColorMaps.getPresetByName(presetName);
|
|
211
|
+
if (preset.EffectiveRange) {
|
|
212
|
+
return [...preset.EffectiveRange] as [number, number];
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class WorkerHandler {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.handler = null;
|
|
4
|
+
onmessage = this.preHandler.bind(this);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
registerHandler(func) {
|
|
8
|
+
this.handler = func;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
preHandler(ev) {
|
|
12
|
+
if (this.handler) {
|
|
13
|
+
const { id, message } = ev.data;
|
|
14
|
+
|
|
15
|
+
let transferables = [];
|
|
16
|
+
const setTransferables = (iter) => {
|
|
17
|
+
transferables = Array.from(iter);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
Promise.resolve(this.handler(message, setTransferables)).then(
|
|
22
|
+
(result) => {
|
|
23
|
+
const msg = {
|
|
24
|
+
id,
|
|
25
|
+
message: result,
|
|
26
|
+
};
|
|
27
|
+
postMessage(msg, transferables);
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
const msg = {
|
|
32
|
+
id,
|
|
33
|
+
error: error.message,
|
|
34
|
+
};
|
|
35
|
+
postMessage(msg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// To be used inside the worker
|
|
42
|
+
export default new WorkerHandler();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps';
|
|
2
|
+
import MedicalPresets from '@/src/vtk/MedicalColorPresets.json';
|
|
3
|
+
|
|
4
|
+
function registerPresets(presets: typeof MedicalPresets) {
|
|
5
|
+
for (let i = 0; i < presets.length; i += 1) {
|
|
6
|
+
vtkColorMaps.addPreset(presets[i]);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
registerPresets(MedicalPresets);
|
|
11
|
+
|
|
12
|
+
/* prettier-ignore */
|
|
13
|
+
const GroupedPresets = [
|
|
14
|
+
{
|
|
15
|
+
group: 'Other',
|
|
16
|
+
presets: [
|
|
17
|
+
'Cool to Warm',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
group: 'CT',
|
|
22
|
+
presets: [
|
|
23
|
+
'CT-AAA',
|
|
24
|
+
'CT-AAA2',
|
|
25
|
+
'CT-Bone',
|
|
26
|
+
'CT-Bones',
|
|
27
|
+
'CT-Cardiac',
|
|
28
|
+
'CT-Cardiac2',
|
|
29
|
+
'CT-Cardiac3',
|
|
30
|
+
'CT-Chest-Contrast-Enhanced',
|
|
31
|
+
'CT-Chest-Vessels',
|
|
32
|
+
'CT-Coronary-Arteries',
|
|
33
|
+
'CT-Coronary-Arteries-2',
|
|
34
|
+
'CT-Coronary-Arteries-3',
|
|
35
|
+
'CT-Cropped-Volume-Bone',
|
|
36
|
+
'CT-Fat',
|
|
37
|
+
'CT-Liver-Vasculature',
|
|
38
|
+
'CT-Lung',
|
|
39
|
+
'CT-MIP',
|
|
40
|
+
'CT-Muscle',
|
|
41
|
+
'CT-Pulmonary-Arteries',
|
|
42
|
+
'CT-Soft-Tissue',
|
|
43
|
+
'CT-Air',
|
|
44
|
+
'CT-X-ray',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
group: 'MR',
|
|
49
|
+
presets: [
|
|
50
|
+
'MR-Default',
|
|
51
|
+
'MR-Angio',
|
|
52
|
+
'MR-MIP',
|
|
53
|
+
'MR-T2-Brain',
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
group: 'DTI',
|
|
58
|
+
presets: [
|
|
59
|
+
'DTI-FA-Brain',
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
group: 'US',
|
|
64
|
+
presets: [
|
|
65
|
+
'US-Fetal',
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
export const DEFAULT_PRESET = 'Cool to Warm';
|
|
71
|
+
export const PresetNameList = GroupedPresets.flatMap((group) => group.presets);
|
|
72
|
+
export default GroupedPresets;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import macro from '@kitware/vtk.js/macro';
|
|
2
|
+
import { Bounds } from '@kitware/vtk.js/types';
|
|
3
|
+
import { vec3 } from 'gl-matrix';
|
|
4
|
+
|
|
5
|
+
function clampPointToBounds(bounds: Bounds, point: vec3) {
|
|
6
|
+
return point.map((p, i) =>
|
|
7
|
+
Math.max(bounds[i * 2], Math.min(bounds[i * 2 + 1], p))
|
|
8
|
+
) as vec3;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function widgetBehavior(publicAPI: any, model: any) {
|
|
12
|
+
model.classHierarchy.push('vtkCrosshairsWidgetProp');
|
|
13
|
+
let isDragging = false;
|
|
14
|
+
|
|
15
|
+
// support setting per-view widget manipulators
|
|
16
|
+
macro.setGet(publicAPI, model, ['manipulator']);
|
|
17
|
+
|
|
18
|
+
// --------------------------------------------------------------------------
|
|
19
|
+
// Interactor events
|
|
20
|
+
// --------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
function ignoreKey(e: any) {
|
|
23
|
+
return e.altKey || e.controlKey || e.shiftKey;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// --------------------------------------------------------------------------
|
|
27
|
+
// Left press: Select handle to drag
|
|
28
|
+
// --------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
publicAPI.handleLeftButtonPress = (e: any) => {
|
|
31
|
+
if (!model.pickable || ignoreKey(e)) {
|
|
32
|
+
return macro.VOID;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
model.widgetState.setPlaced(true);
|
|
36
|
+
isDragging = true;
|
|
37
|
+
model._interactor.requestAnimation(publicAPI);
|
|
38
|
+
model._apiSpecificRenderWindow.setCursor('crosshairs');
|
|
39
|
+
publicAPI.invokeStartInteractionEvent();
|
|
40
|
+
publicAPI.handleMouseMove(e);
|
|
41
|
+
return macro.EVENT_ABORT;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// --------------------------------------------------------------------------
|
|
45
|
+
// Mouse move: Drag selected handle / Handle follow the mouse
|
|
46
|
+
// --------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
publicAPI.handleMouseMove = (callData: any) => {
|
|
49
|
+
// technically need to call requestAnimation during
|
|
50
|
+
// the initial phase of placing the crosshairs,
|
|
51
|
+
// but that's not needed since no VTK object
|
|
52
|
+
// is actually being rendered.
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
(!model.widgetState.getPlaced() || isDragging) &&
|
|
56
|
+
model.pickable &&
|
|
57
|
+
model.manipulator &&
|
|
58
|
+
!ignoreKey(callData)
|
|
59
|
+
) {
|
|
60
|
+
const worldCoordsOfPointer = model.manipulator.handleEvent(
|
|
61
|
+
callData,
|
|
62
|
+
model._apiSpecificRenderWindow
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const handle = model.widgetState.getHandle();
|
|
66
|
+
const worldToIndex = model.widgetState.getWorldToIndex();
|
|
67
|
+
const indexToWorld = model.widgetState.getIndexToWorld();
|
|
68
|
+
if (worldToIndex.length && indexToWorld.length) {
|
|
69
|
+
const indexCoordsOfPointer = vec3.create();
|
|
70
|
+
const worldOrigin = vec3.create();
|
|
71
|
+
const bounds = handle.getBounds();
|
|
72
|
+
|
|
73
|
+
vec3.transformMat4(
|
|
74
|
+
indexCoordsOfPointer,
|
|
75
|
+
worldCoordsOfPointer,
|
|
76
|
+
worldToIndex
|
|
77
|
+
);
|
|
78
|
+
const indexOrigin = clampPointToBounds(bounds, indexCoordsOfPointer);
|
|
79
|
+
vec3.transformMat4(worldOrigin, indexOrigin, indexToWorld);
|
|
80
|
+
|
|
81
|
+
handle.setOrigin(worldOrigin);
|
|
82
|
+
publicAPI.invokeInteractionEvent();
|
|
83
|
+
return macro.EVENT_ABORT;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return macro.VOID;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// --------------------------------------------------------------------------
|
|
91
|
+
// Left release: Finish drag / Create new handle
|
|
92
|
+
// --------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
publicAPI.handleLeftButtonRelease = () => {
|
|
95
|
+
if (isDragging && model.pickable) {
|
|
96
|
+
model._interactor.cancelAnimation(publicAPI);
|
|
97
|
+
model._apiSpecificRenderWindow.setCursor('default');
|
|
98
|
+
publicAPI.invokeEndInteractionEvent();
|
|
99
|
+
}
|
|
100
|
+
isDragging = false;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// --------------------------------------------------------------------------
|
|
104
|
+
// Focus API - modeHandle follow mouse when widget has focus
|
|
105
|
+
// --------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
publicAPI.grabFocus = () => {};
|
|
108
|
+
|
|
109
|
+
// --------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
publicAPI.loseFocus = () => {};
|
|
112
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import vtkAbstractWidget from '@kitware/vtk.js/Widgets/Core/AbstractWidget';
|
|
2
|
+
import vtkAbstractWidgetFactory from '@kitware/vtk.js/Widgets/Core/AbstractWidgetFactory';
|
|
3
|
+
import vtkPlaneManipulator from '@kitware/vtk.js/Widgets/Manipulators/PlaneManipulator';
|
|
4
|
+
import { mat4, vec3 } from 'gl-matrix';
|
|
5
|
+
import { CrosshairsWidgetState } from './state';
|
|
6
|
+
|
|
7
|
+
export interface vtkCrosshairsViewWidget extends vtkAbstractWidget {
|
|
8
|
+
setManipulator(manipulator: vtkPlaneManipulator): boolean;
|
|
9
|
+
getManipulator(): vtkPlaneManipulator;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface vtkCrosshairsWidget extends vtkAbstractWidgetFactory {
|
|
13
|
+
getWidgetState(): CrosshairsWidgetState;
|
|
14
|
+
getManipulator(): vtkPlaneManipulator;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function newInstance(): vtkCrosshairsWidget;
|
|
18
|
+
|
|
19
|
+
export declare const vtkCrosshairsWidget: {
|
|
20
|
+
newInstance: typeof newInstance;
|
|
21
|
+
};
|
|
22
|
+
export default vtkCrosshairsWidget;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import macro from '@kitware/vtk.js/macro';
|
|
2
|
+
import vtkAbstractWidgetFactory from '@kitware/vtk.js/Widgets/Core/AbstractWidgetFactory';
|
|
3
|
+
import vtkPlanePointManipulator from '@kitware/vtk.js/Widgets/Manipulators/PlaneManipulator';
|
|
4
|
+
|
|
5
|
+
import { ViewTypes } from '@kitware/vtk.js/Widgets/Core/WidgetManager/Constants';
|
|
6
|
+
|
|
7
|
+
import stateGenerator from './state';
|
|
8
|
+
import widgetBehavior from './behavior';
|
|
9
|
+
|
|
10
|
+
// ----------------------------------------------------------------------------
|
|
11
|
+
// Factory
|
|
12
|
+
// ----------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
function vtkCrosshairsWidget(publicAPI, model) {
|
|
15
|
+
model.classHierarchy.push('vtkCrosshairsWidget');
|
|
16
|
+
|
|
17
|
+
// --- Widget Requirement ---------------------------------------------------
|
|
18
|
+
|
|
19
|
+
model.behavior = widgetBehavior;
|
|
20
|
+
model.widgetState = stateGenerator();
|
|
21
|
+
|
|
22
|
+
publicAPI.getRepresentationsForViewType = (viewType) => {
|
|
23
|
+
switch (viewType) {
|
|
24
|
+
case ViewTypes.DEFAULT:
|
|
25
|
+
case ViewTypes.GEOMETRY:
|
|
26
|
+
case ViewTypes.SLICE:
|
|
27
|
+
case ViewTypes.VOLUME:
|
|
28
|
+
default:
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// --------------------------------------------------------------------------
|
|
34
|
+
// initialization
|
|
35
|
+
// --------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
model.widgetState.onBoundsChange((bounds) => {
|
|
38
|
+
const center = [
|
|
39
|
+
(bounds[0] + bounds[1]) * 0.5,
|
|
40
|
+
(bounds[2] + bounds[3]) * 0.5,
|
|
41
|
+
(bounds[4] + bounds[5]) * 0.5,
|
|
42
|
+
];
|
|
43
|
+
model.widgetState.getHandle().setOrigin(center);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Default manipulator
|
|
47
|
+
model.manipulator = vtkPlanePointManipulator.newInstance();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ----------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
const DEFAULT_VALUES = {
|
|
53
|
+
// manipulator: null,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// ----------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
export function extend(publicAPI, model, initialValues = {}) {
|
|
59
|
+
Object.assign(model, DEFAULT_VALUES, initialValues);
|
|
60
|
+
|
|
61
|
+
vtkAbstractWidgetFactory.extend(publicAPI, model, initialValues);
|
|
62
|
+
macro.setGet(publicAPI, model, ['manipulator']);
|
|
63
|
+
|
|
64
|
+
vtkCrosshairsWidget(publicAPI, model);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ----------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
export const newInstance = macro.newInstance(extend, 'vtkCrosshairsWidget');
|
|
70
|
+
|
|
71
|
+
// ----------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
export default { newInstance, extend };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Bounds, Vector3 } from '@kitware/vtk.js/types';
|
|
2
|
+
import vtkStateBuilder from '@kitware/vtk.js/Widgets/Core/StateBuilder';
|
|
3
|
+
import vtkWidgetState from '@kitware/vtk.js/Widgets/Core/WidgetState';
|
|
4
|
+
import { mat4 } from 'gl-matrix';
|
|
5
|
+
|
|
6
|
+
export interface CrosshairsHandleWidgetState extends vtkWidgetState {
|
|
7
|
+
setOrigin(origin: Vector3 | null): boolean;
|
|
8
|
+
getOrigin(): Vector3 | null;
|
|
9
|
+
setScale1(scale: number): boolean;
|
|
10
|
+
getScale1(): number;
|
|
11
|
+
setVisible(visible: boolean): boolean;
|
|
12
|
+
getVisible(): boolean;
|
|
13
|
+
setBounds(bounds: Bounds): boolean;
|
|
14
|
+
getBounds(): Bounds;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface CrosshairsWidgetState extends vtkWidgetState {
|
|
18
|
+
setPlaced(placed: boolean): boolean;
|
|
19
|
+
getPlaced(): boolean;
|
|
20
|
+
setIndexToWorld(indexToWorld: mat4): boolean;
|
|
21
|
+
getIndexToWorld(): mat4;
|
|
22
|
+
setWorldToIndex(worldToIndex: mat4): boolean;
|
|
23
|
+
getWorldToIndex(): mat4;
|
|
24
|
+
getHandle(): CrosshairsHandleWidgetState;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function generateState() {
|
|
28
|
+
return vtkStateBuilder
|
|
29
|
+
.createBuilder()
|
|
30
|
+
.addField({
|
|
31
|
+
name: 'placed',
|
|
32
|
+
initialValue: false,
|
|
33
|
+
})
|
|
34
|
+
.addField({
|
|
35
|
+
name: 'indexToWorld',
|
|
36
|
+
initialValue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
37
|
+
})
|
|
38
|
+
.addField({
|
|
39
|
+
name: 'worldToIndex',
|
|
40
|
+
initialValue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
41
|
+
})
|
|
42
|
+
.addStateFromMixin({
|
|
43
|
+
labels: ['handle'],
|
|
44
|
+
mixins: ['origin', 'bounds'],
|
|
45
|
+
name: 'handle',
|
|
46
|
+
initialValues: {
|
|
47
|
+
origin: null,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
.build();
|
|
51
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import vtkSliceRepresentationProxy from '@kitware/vtk.js/Proxy/Core/SliceRepresentationProxy';
|
|
2
|
+
|
|
3
|
+
export interface vtkIJKSliceRepresentationProxy
|
|
4
|
+
extends vtkSliceRepresentationProxy {
|
|
5
|
+
setOpacity(opacity: number): boolean;
|
|
6
|
+
getOpacity(): number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default vtkIJKSliceRepresentationProxy;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import macro from '@kitware/vtk.js/macro';
|
|
2
|
+
|
|
3
|
+
import vtkSliceRepresentationProxy from '@kitware/vtk.js/Proxy/Representations/SliceRepresentationProxy';
|
|
4
|
+
|
|
5
|
+
const SLICE_MODE_MAP = {
|
|
6
|
+
X: 'I',
|
|
7
|
+
Y: 'J',
|
|
8
|
+
Z: 'K',
|
|
9
|
+
I: 'I',
|
|
10
|
+
J: 'J',
|
|
11
|
+
K: 'K',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function vtkIJKSliceRepresentationProxy(publicAPI, model) {
|
|
15
|
+
model.classHierarchy.push('vtkIJKSliceRepresentationProxy');
|
|
16
|
+
|
|
17
|
+
const superClass = { ...publicAPI };
|
|
18
|
+
|
|
19
|
+
// don't set colors on slices
|
|
20
|
+
publicAPI.setColorBy = () => {};
|
|
21
|
+
|
|
22
|
+
// pretend XYZ slicing is actually just IJK.
|
|
23
|
+
publicAPI.setSlicingMode = (modeString) => {
|
|
24
|
+
return superClass.setSlicingMode(SLICE_MODE_MAP[modeString]);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ----------------------------------------------------------------------------
|
|
29
|
+
// Object factory
|
|
30
|
+
// ----------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
const DEFAULT_VALUES = {};
|
|
33
|
+
|
|
34
|
+
// ----------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
export function extend(publicAPI, model, initialValues = {}) {
|
|
37
|
+
Object.assign(model, DEFAULT_VALUES, initialValues);
|
|
38
|
+
|
|
39
|
+
// Object methods
|
|
40
|
+
vtkSliceRepresentationProxy.extend(publicAPI, model);
|
|
41
|
+
|
|
42
|
+
macro.proxyPropertyMapping(publicAPI, model, {
|
|
43
|
+
opacity: { modelKey: 'property', property: 'opacity' },
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Object specific methods
|
|
47
|
+
vtkIJKSliceRepresentationProxy(publicAPI, model);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ----------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
export const newInstance = macro.newInstance(
|
|
53
|
+
extend,
|
|
54
|
+
'vtkIJKSliceRepresentationProxy'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// ----------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
export default { newInstance, extend };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import { vtkView2DProxy } from '@kitware/vtk.js/Proxy/Core/View2DProxy';
|
|
3
|
+
import { ViewProxyCustomizations } from '@src/vtk/LPSView3DProxy';
|
|
4
|
+
|
|
5
|
+
export interface vtkLPSView2DProxy
|
|
6
|
+
extends vtkView2DProxy,
|
|
7
|
+
ViewProxyCustomizations {
|
|
8
|
+
resizeToFit(lookAxis: Vector3, viewUpAxis: Vector3, worldDims: Vector3);
|
|
9
|
+
resetCamera(boundsToUse?: number[]);
|
|
10
|
+
/**
|
|
11
|
+
* @param mode One of IJKXYZ
|
|
12
|
+
*/
|
|
13
|
+
setSlicingMode(mode: string);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// TODO extend, newInstance...
|
|
17
|
+
export declare const vtkLPSView2DProxy: {};
|
|
18
|
+
export default vtkLPSView2DProxy;
|