Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c39dc86
fix(handleEvent): worldCoords type mismatch
jadh4v Jun 20, 2023
377aae6
feat(ObliqueView): add a new Oblique View using vtkImageResliceMapper
jadh4v Jun 22, 2023
0f39e36
feat(ObliqueView): add ResliceCursorWidget to control oblique views
jadh4v Jul 13, 2023
d946b19
fix(VtkObliqueView): update view slice issue
jadh4v Jul 21, 2023
2d3ac93
fix(ResliceCursor): thinner footprint
jadh4v Aug 2, 2023
d24f563
feat(ObliqueView): add colored outlines to oblique planes
jadh4v Aug 3, 2023
6082711
fix(ObliqueView): correct the reset camera behavior
jadh4v Aug 11, 2023
1de788e
feat(resetViews): Add a global button to reset all views in layout
jadh4v Aug 18, 2023
1418039
fix: placement of useVTKCallback
jadh4v Aug 18, 2023
fc24649
fix(resliceCursor): add opacity to handles and lines
jadh4v Aug 23, 2023
bc5ed8f
feat(resetViews): connect event with TwoView and ThreeView
jadh4v Aug 23, 2023
8f6b0c7
fix(ResliceCursorWidget): single App-level instance
jadh4v Aug 23, 2023
ea975fc
feat(Oblique3D): add 3D view in Oblique layout
jadh4v Aug 23, 2023
36934e5
fix(oblique2D): remove internal camera-reset buttons
jadh4v Sep 21, 2023
a196e3b
fix(Oblique): sync outline colors with orientation box
jadh4v Sep 25, 2023
90bc5d1
fix(Oblique3D): change to use a composite representation proxy
jadh4v Sep 27, 2023
744c52b
fix(resetViews): use createEventHook in place of store for events
jadh4v Sep 28, 2023
0c83389
fix: import paths and onVTKEvent updates after rebase
jadh4v Sep 28, 2023
4570aac
fix(ToolStrip): disable tools that don't work in oblique layout
jadh4v Sep 28, 2023
801e54b
chore: run prettify
jadh4v Oct 10, 2023
64cb97c
fix(VTKResliceCursor): make injected value as non-ref
jadh4v Oct 10, 2023
4181a04
fix(VtkObliqueView): use anatomical axes for oblique planes
jadh4v Oct 26, 2023
28c483b
test(e2e): update prostrate linux baseline
floryst Oct 27, 2023
1f7747a
test(e2e): update prostate macos baseline
floryst Oct 27, 2023
a0317ea
fix(Layouts-menu): close menu after selection
jadh4v Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion src/components/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
@click="handleSave"
/>
<div class="my-1 tool-separator" />
<v-menu location="right" :close-on-content-click="false">
<v-menu location="right" :close-on-content-click="true">
<template v-slot:activator="{ props }">
<div>
<tool-button
Expand Down Expand Up @@ -224,6 +224,7 @@ import {
defineComponent,
nextTick,
onMounted,
provide,
Ref,
ref,
watch,
Expand All @@ -242,6 +243,12 @@ import {
ImportDataSourcesResult,
convertSuccessResultToDataSelection,
} from '@/src/io/import/importDataSources';
import vtkResliceCursorWidget, {
ResliceCursorWidgetState,
} from '@kitware/vtk.js/Widgets/Widgets3D/ResliceCursorWidget';
import { useCurrentImage } from '@/src/composables/useCurrentImage';
import type { Vector3 } from '@kitware/vtk.js/types';
import { ViewTypes } from '@kitware/vtk.js/Widgets/Core/WidgetManager/Constants';
import ToolButton from './ToolButton.vue';
import LayoutGrid from './LayoutGrid.vue';
import ModulePanel from './ModulePanel.vue';
Expand Down Expand Up @@ -275,6 +282,7 @@ import { useWebGLWatchdog } from '../composables/useWebGLWatchdog';
import { useAppLoadingNotifications } from '../composables/useAppLoadingNotifications';
import { partition, wrapInArray } from '../utils';
import { useKeyboardShortcuts } from '../composables/useKeyboardShortcuts';
import { VTKResliceCursor } from '../constants';

async function loadFiles(
sources: DataSource[],
Expand Down Expand Up @@ -365,6 +373,7 @@ export default defineComponent({
useKeyboardShortcuts();

const { runAsLoading } = useAppLoadingNotifications();
const { currentImageData, currentImageMetadata } = useCurrentImage();

// --- layout --- //

Expand All @@ -391,6 +400,62 @@ export default defineComponent({
}
});

// --- ResliceCursorWidget --- //
// Construct the common instance of vtkResliceCursorWidget and provide it
// to all the child ObliqueView components.
const resliceCursor = vtkResliceCursorWidget.newInstance({
scaleInPixels: true,
rotationHandlePosition: 0.75,
}) as vtkResliceCursorWidget;
provide(VTKResliceCursor, resliceCursor);

// TODO: Move this to a store/global-state for reslicing.
// Orient the planes of the vtkResliceCursorWidget to the orientation
// of the currently set image.
const resliceCursorState =
resliceCursor.getWidgetState() as ResliceCursorWidgetState;

// Temporary fix to disable race between PanTool and ResliceCursorWidget
resliceCursorState.setScrollingMethod(-1);

watch(currentImageData, (image) => {
if (image && resliceCursor) {
resliceCursor.setImage(image);
// Reset to default plane values before transforming based on current image-data.
resliceCursorState.setPlanes({
[ViewTypes.YZ_PLANE]: {
normal: [1, 0, 0],
viewUp: [0, 0, 1],
},
[ViewTypes.XZ_PLANE]: {
normal: [0, -1, 0],
viewUp: [0, 0, 1],
},
[ViewTypes.XY_PLANE]: {
normal: [0, 0, -1],
viewUp: [0, -1, 0],
},
});
const planes = resliceCursorState.getPlanes();
if (currentImageMetadata.value) {
planes[ViewTypes.XY_PLANE].normal = currentImageMetadata.value
.lpsOrientation.Inferior as Vector3;
planes[ViewTypes.XY_PLANE].viewUp = currentImageMetadata.value
.lpsOrientation.Anterior as Vector3;

planes[ViewTypes.XZ_PLANE].normal = currentImageMetadata.value
.lpsOrientation.Anterior as Vector3;
planes[ViewTypes.XZ_PLANE].viewUp = currentImageMetadata.value
.lpsOrientation.Superior as Vector3;

planes[ViewTypes.YZ_PLANE].normal = currentImageMetadata.value
.lpsOrientation.Left as Vector3;
planes[ViewTypes.YZ_PLANE].viewUp = currentImageMetadata.value
.lpsOrientation.Superior as Vector3;
}
}
});

// --- file handling --- //

async function openFiles(files: FileList | null) {
Expand Down
4 changes: 4 additions & 0 deletions src/components/LayoutGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import { Component, computed, defineComponent, PropType, toRefs } from 'vue';
import { storeToRefs } from 'pinia';
import VtkTwoView from './VtkTwoView.vue';
import VtkObliqueView from './VtkObliqueView.vue';
import VtkObliqueThreeView from './VtkObliqueThreeView.vue';
import VtkThreeView from './VtkThreeView.vue';
import { Layout, LayoutDirection } from '../types/layout';
import { useViewStore } from '../store/views';
Expand All @@ -30,6 +32,8 @@ import { ViewType } from '../types/views';
const TYPE_TO_COMPONENT: Record<ViewType, Component> = {
'2D': VtkTwoView,
'3D': VtkThreeView,
Oblique: VtkObliqueView,
Oblique3D: VtkObliqueThreeView,
};

export default defineComponent({
Expand Down
24 changes: 18 additions & 6 deletions src/components/ToolStrip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
icon="mdi-crosshairs"
name="Crosshairs"
:buttonClass="['tool-btn', active ? 'tool-btn-selected' : '']"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
/>
</groupable-item>
Expand All @@ -64,7 +64,7 @@
icon="mdi-brush"
name="Paint"
:active="active"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
>
<paint-controls />
Expand All @@ -79,7 +79,7 @@
name="Rectangle"
:mobileOnlyMenu="true"
:active="active"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
>
<rectangle-controls />
Expand All @@ -91,7 +91,7 @@
name="Polygon"
:mobileOnlyMenu="true"
:active="active"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
>
<polygon-controls />
Expand All @@ -103,7 +103,7 @@
name="Ruler"
:mobileOnlyMenu="true"
:active="active"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
>
<ruler-controls />
Expand All @@ -116,27 +116,32 @@
icon="mdi-crop"
name="Crop"
:active="active"
:disabled="noCurrentImage"
:disabled="noCurrentImage || isObliqueLayout"
@click="toggle"
>
<crop-controls />
</menu-tool-button>
</groupable-item>
<div class="my-1 tool-separator" />
<reset-views />
</item-group>
</template>

<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { onKeyDown } from '@vueuse/core';
import { Tools } from '@/src/store/tools/types';
import ToolButton from './ToolButton.vue';
import ItemGroup from './ItemGroup.vue';
import GroupableItem from './GroupableItem.vue';
import { useDatasetStore } from '../store/datasets';
import { useToolStore } from '../store/tools';
import { useViewStore } from '../store/views';
import PaintControls from './PaintControls.vue';
import MenuToolButton from './MenuToolButton.vue';
import CropControls from './tools/crop/CropControls.vue';
import ResetViews from './tools/ResetViews.vue';
import RulerControls from './RulerControls.vue';
import RectangleControls from './RectangleControls.vue';
import PolygonControls from './PolygonControls.vue';
Expand All @@ -150,6 +155,7 @@ export default defineComponent({
GroupableItem,
PaintControls,
CropControls,
ResetViews,
RulerControls,
RectangleControls,
PolygonControls,
Expand All @@ -158,9 +164,14 @@ export default defineComponent({
setup() {
const dataStore = useDatasetStore();
const toolStore = useToolStore();
const viewStore = useViewStore();

const noCurrentImage = computed(() => !dataStore.primaryDataset);
const currentTool = computed(() => toolStore.currentTool);
const { layout: currentLayout } = storeToRefs(viewStore);
const isObliqueLayout = computed(
() => currentLayout.value?.name === 'Oblique View'
);

const paintMenu = ref(false);
const cropMenu = ref(false);
Expand All @@ -176,6 +187,7 @@ export default defineComponent({
currentTool,
setCurrentTool: toolStore.setCurrentTool,
noCurrentImage,
isObliqueLayout,
Tools,
paintMenu,
cropMenu,
Expand Down
Loading