Skip to content

Commit

Permalink
feat(polygon): use common component factory
Browse files Browse the repository at this point in the history
  • Loading branch information
floryst committed Sep 14, 2023
1 parent 44efe88 commit 688b696
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 426 deletions.
9 changes: 8 additions & 1 deletion src/components/tools/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AnnotationToolStore } from '@/src/store/tools/useAnnotationTool';
import { Maybe } from '@/src/types';
import { AnnotationTool } from '@/src/types/annotation-tool';
import { vtkAnnotationToolWidget } from '@/src/vtk/ToolWidgetUtils/utils';
import vtkAbstractWidgetFactory from '@kitware/vtk.js/Widgets/Core/AbstractWidgetFactory';
import vtkWidgetState from '@kitware/vtk.js/Widgets/Core/WidgetState';
Expand Down Expand Up @@ -59,10 +60,16 @@ export interface WidgetComponentMeta<

/**
* An optional render function
*
* @param viewId the view ID
* @param syncedState the synced state from the widget
* @param labelProps the label props associated with the tool
* @param tool an optional tool. Not available for the placing widget.
*/
render?: (
viewId: string,
syncedState: SyncedState,
labelProps: Maybe<ToolStore['labels'][string]>
labelProps: Maybe<ToolStore['labels'][string]>,
tool?: AnnotationTool<ToolID>
) => VNode;
}
7 changes: 6 additions & 1 deletion src/components/tools/createWidget2DComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,12 @@ export function createWidget2DComponent<

return () =>
currentSlice.value === tool.value.slice
? meta.render?.(viewId.value, syncedState, labelProps.value)
? meta.render?.(
viewId.value,
syncedState,
labelProps.value,
tool.value
)
: null;
},
});
Expand Down
152 changes: 0 additions & 152 deletions src/components/tools/polygon/PlacingPolygonWidget2D.vue

This file was deleted.

186 changes: 71 additions & 115 deletions src/components/tools/polygon/PolygonTool.vue
Original file line number Diff line number Diff line change
@@ -1,127 +1,83 @@
<template>
<div class="overlay-no-events">
<svg class="overlay-no-events">
<polygon-widget-2D
v-for="tool in tools"
:key="tool.id"
:tool-id="tool.id"
:current-slice="currentSlice"
:view-id="viewId"
:view-direction="viewDirection"
:widget-manager="widgetManager"
@contextmenu="openContextMenu(tool.id, $event)"
/>
<placing-polygon-widget-2D
v-if="isToolActive"
:current-slice="currentSlice"
:color="activeLabelColor"
:view-id="viewId"
:view-direction="viewDirection"
:widget-manager="widgetManager"
@placed="onToolPlaced"
/>
</svg>
<annotation-context-menu ref="contextMenu" :tool-store="activeToolStore" />
</div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, toRefs } from 'vue';
import { storeToRefs } from 'pinia';
import { useCurrentImage } from '@/src/composables/useCurrentImage';
import { useToolStore } from '@/src/store/tools';
import { Tools } from '@/src/store/tools/types';
import { getLPSAxisFromDir } from '@/src/utils/lps';
import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager';
import { LPSAxisDir } from '@/src/types/lps';
import { createAnnotationToolComponent } from '@/src/components/tools/createAnnotationToolComponent';
import { createPlacingWidget2DComponent } from '@/src/components/tools/createPlacingWidget2DComponent';
import { createWidget2DComponent } from '@/src/components/tools/createWidget2DComponent';
import { usePolygonStore } from '@/src/store/tools/polygons';
import { Tools } from '@/src/store/tools/types';
import type { PolygonStore } from '@/src/store/tools/polygons';
import vtkPolygonWidget, {
vtkPolygonViewWidget,
vtkPolygonWidgetState,
} from '@/src/vtk/PolygonWidget';
import {
useContextMenu,
useCurrentTools,
} from '@/src/composables/annotationTool';
import { useCurrentFrameOfReference } from '@/src/composables/useCurrentFrameOfReference';
import AnnotationContextMenu from '@/src/components/tools/AnnotationContextMenu.vue';
import PlacingPolygonWidget2D from '@/src/components/tools/polygon/PlacingPolygonWidget2D.vue';
import { PolygonInitState } from '@/src/components/tools/polygon/common';
import PolygonWidget2D from './PolygonWidget2D.vue';
PolygonInitState,
PolygonSyncedState,
useSyncedPolygonState,
} from '@/src/components/tools/polygon/common';
import { WidgetComponentMeta } from '@/src/components/tools/common';
import PolygonSVG2D from '@/src/components/tools/polygon/PolygonSVG2D.vue';
import createStandaloneState from '@/src/vtk/PolygonWidget/standaloneState';
import createPolygonWidgetState from '@/src/vtk/PolygonWidget/storeState';
import { PolygonID } from '@/src/types/polygon';
import { AnnotationToolStore } from '@/src/store/tools/useAnnotationTool';
import { h } from 'vue';
const useActiveToolStore = usePolygonStore;
const toolType = Tools.Polygon;
export default defineComponent({
name: 'PolygonTool',
props: {
viewId: {
type: String,
required: true,
},
currentSlice: {
type: Number,
required: true,
},
viewDirection: {
type: String as PropType<LPSAxisDir>,
required: true,
},
widgetManager: {
type: Object as PropType<vtkWidgetManager>,
required: true,
},
const componentMeta: WidgetComponentMeta<
PolygonID,
PolygonStore,
vtkPolygonWidgetState,
vtkPolygonWidget,
vtkPolygonViewWidget,
PolygonSyncedState,
PolygonInitState
> = {
name: 'PolygonWidget',
useToolStore: usePolygonStore,
createStandaloneState: () => createStandaloneState() as vtkPolygonWidgetState,
createStoreBackedState: (toolId: string, store: PolygonStore) =>
createPolygonWidgetState({ id: toolId, store }),
createWidgetFactory: (widgetState) =>
vtkPolygonWidget.newInstance({ widgetState }),
useSyncedState: useSyncedPolygonState,
resetPlacingWidget: (widget) => {
widget.reset();
widget.getWidgetState().setPlacing(true);
},
components: {
PolygonWidget2D,
PlacingPolygonWidget2D,
AnnotationContextMenu,
},
setup(props) {
const { viewDirection, currentSlice } = toRefs(props);
const toolStore = useToolStore();
const activeToolStore = useActiveToolStore();
const { activeLabel } = storeToRefs(activeToolStore);
const { currentImageID } = useCurrentImage();
const isToolActive = computed(() => toolStore.currentTool === toolType);
const viewAxis = computed(() => getLPSAxisFromDir(viewDirection.value));
const currentFrameOfReference = useCurrentFrameOfReference(
viewDirection,
currentSlice
);
const onToolPlaced = (initState: PolygonInitState) => {
if (!currentImageID.value) return;
activeToolStore.addTool({
imageID: currentImageID.value,
frameOfReference: currentFrameOfReference.value,
slice: currentSlice.value,
label: activeLabel.value,
color: activeLabel.value
? activeToolStore.labels[activeLabel.value].color
: undefined,
points: initState.points,
});
constructInitState: (syncedState) => {
return {
points: syncedState.points,
};
},
render: (viewId, syncedState, labelProps, tool) => {
return h(PolygonSVG2D, {
viewId,
points: syncedState.points,
color: labelProps?.color,
movePoint: syncedState.movePoint,
placing: !tool,
});
},
};
// --- right-click menu --- //
const { contextMenu, openContextMenu } = useContextMenu();
const Widget2DComponent = createWidget2DComponent({
...componentMeta,
name: 'PolygonWidget2D',
});
const currentTools = useCurrentTools(activeToolStore, viewAxis);
const PlacingWidget2DComponent = createPlacingWidget2DComponent({
...componentMeta,
name: 'PlacingPolygonWidget2D',
});
return {
tools: currentTools,
isToolActive,
activeLabelColor: computed(() => {
return (
activeLabel.value && activeToolStore.labels[activeLabel.value].color
);
}),
onToolPlaced,
contextMenu,
openContextMenu,
activeToolStore,
};
},
export default createAnnotationToolComponent<
PolygonID,
AnnotationToolStore<PolygonID>
>({
name: 'PolygonTool',
type: Tools.Polygon,
useToolStore: usePolygonStore,
Widget2DComponent,
PlacingWidget2DComponent,
});
</script>

Expand Down
Loading

0 comments on commit 688b696

Please sign in to comment.