diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue index 68714485..1395e562 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue @@ -123,6 +123,10 @@ export default { type: Number, required: true }, + activeTool: { + type: String, + default: '' + }, }, data() { return { @@ -254,9 +258,14 @@ export default { this.defaultWindowLevel.windowCenter = windowCenter this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}` } - const toolGroupId = this.viewportId - const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId) - toolGroup.setToolEnabled('ScaleOverlay') + const toolGroup = + cornerstoneTools.ToolGroupManager.getToolGroupForViewport( + this.viewportId, + this.renderingEngineId + ) || cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId) + if (toolGroup) { + toolGroup.setToolEnabled('ScaleOverlay') + } } }, @@ -829,6 +838,7 @@ export default { this.sliderInfo.isMove = false }, handletoolsMouseWheel(e) { + if (this.activeTool === 'Crosshairs') return const { viewportId, wheel } = e.detail if (this.isMip) { const container = document.getElementById('rotateBar') @@ -852,6 +862,7 @@ export default { this.rotateBarInfo.isMove = false }, rotateBarMousemove(e) { + if (this.activeTool === 'Crosshairs') return // 滚动旋转 if (!this.rotateBarInfo.isMove) return const container = document.getElementById('rotateBar') @@ -867,6 +878,7 @@ export default { this.rotateBarLeft = x }, rotateBarMousedown(e) { + if (this.activeTool === 'Crosshairs') return this.rotateBarInfo.initLeft = e.srcElement.offsetLeft this.rotateBarInfo.initX = e.clientX this.rotateBarInfo.isMove = true @@ -905,6 +917,7 @@ export default { viewport.render() }, clickRotate(e) { + if (this.activeTool === 'Crosshairs') return // console.log('clickRotate') const container = document.getElementById('rotateBar') const containerWidth = container.offsetWidth diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue index 5755b0d0..0187fb52 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -180,6 +180,11 @@ @click.prevent="openFusion"> +
+ +
+ @dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)" + @mouseenter="hoverFusionViewport(index)" @mouseleave="hoverFusionViewport(-1)">
+
+
+
@@ -763,6 +772,7 @@ export default { isMPR: false, volumeToolGroupId: "share-viewport-volume", + fusionToolGroupId: "share-viewport-fusion", MPRInfo: { AXIAL: { imageNum: 0 @@ -1396,6 +1406,7 @@ export default { const fusionElement2 = this.$refs['viewport-fusion-1'][0].$el const fusionElement3 = this.$refs['viewport-fusion-2'][0].$el const fusionElement4 = this.$refs['viewport-fusion-3'][0].$el + const fusionHiddenSag = this.$refs['viewport-fusion-hidden-sag'] const arr = [ { viewportId: 'viewport-fusion-0', @@ -1430,10 +1441,19 @@ export default { orientation: Enums.OrientationAxis.CORONAL, background: [1, 1, 1] } + }, + { + viewportId: 'viewport-fusion-hidden-sag', + type: ViewportType.ORTHOGRAPHIC, + element: fusionHiddenSag, + defaultOptions: { + orientation: Enums.OrientationAxis.SAGITTAL, + background: [1, 1, 1] + } } ] viewportInputArray = [...viewportInputArray, ...arr] - viewportIds = viewportIds.concat(fusionViewportIds) + viewportIds = viewportIds.concat(fusionViewportIds, ['viewport-fusion-hidden-sag']) } renderingEngine.setViewports(viewportInputArray) this.addAnnotationListeners() @@ -1469,6 +1489,8 @@ export default { let toolGroupId = viewportId if (volumeViewportIds.includes(viewportId)) { toolGroupId = this.volumeToolGroupId + } else if (viewportId.startsWith('viewport-fusion-')) { + toolGroupId = this.fusionToolGroupId } const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) ? ToolGroupManager.getToolGroup(toolGroupId) : ToolGroupManager.createToolGroup(toolGroupId) @@ -1564,6 +1586,11 @@ export default { toolGroup.addTool(CrosshairsTool.toolName, { getReferenceLineColor: this.setCrosshairsToolLineColor }); + } else if (toolGroupId === this.fusionToolGroupId) { + toolGroup.addTool(CrosshairsTool.toolName, { + getReferenceLineColor: this.setCrosshairsToolLineColor, + getReferenceLineSlabThicknessControlsOn: (otherViewportId) => otherViewportId !== 'viewport-fusion-3' + }); } else { toolGroup.addTool(WindowLevelTool.toolName) } @@ -1606,26 +1633,19 @@ export default { getTextLines: this.getEllipticalROIToolTextLines }) toolGroup.addTool(FixedRadiusCircleROITool.toolName, { - radius: Number.isFinite(this.taskInfo.CircleRadius) ? this.taskInfo.CircleRadius : 1, - getTextLines: this.getCircleROIToolTextLines - }) + radius: Number.isFinite(this.taskInfo.CircleRadius) ? this.taskInfo.CircleRadius : 1, + getTextLines: this.getCircleROIToolTextLines + }) toolGroup.addTool(AngleTool.toolName, { getTextLines: this.getAngleToolTextLines }) toolGroup.addTool(CobbAngleTool.toolName, { getTextLines: this.getCobbAngleToolTextLines }) - if (toolGroupId === 'viewport-fusion-3') { + if (viewportId === 'viewport-fusion-3') { toolGroup.addTool(VolumeRotateTool.toolName) - toolGroup.setToolActive(VolumeRotateTool.toolName, { - bindings: [ - { - mouseButton: MouseBindings.Wheel // mouse wheel - } - ] - }) toolGroup.addTool(MIPJumpToClickTool.toolName, { - targetViewportIds: fusionViewportIds.filter((id) => id !== toolGroupId) + targetViewportIds: fusionViewportIds.filter((id) => id !== viewportId) }) // Set the initial state of the tools, here we set one tool active on left click. @@ -2488,22 +2508,61 @@ export default { const factor = 10 ** precision return (Math.round(num * factor + 0.0000001) / factor).toFixed(precision) }, + getActiveToolGroupId() { + if (this.isMPR) return this.volumeToolGroupId + if (this.isFusion) return this.fusionToolGroupId + return `${this.viewportKey}-${this.activeViewportIndex}` + }, + getCurrentToolGroupIds() { + if (this.isMPR) return [this.volumeToolGroupId] + if (this.isFusion) return [this.fusionToolGroupId] + return [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`] + }, + setFusionMipJumpEnabled(enabled) { + if (!this.isFusion) return + const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId) + if (!toolGroup || !toolGroup.hasTool(MIPJumpToClickTool.toolName)) return + if (enabled) { + toolGroup.setToolActive(MIPJumpToClickTool.toolName, { + bindings: [{ mouseButton: MouseBindings.Primary }] + }) + } else { + toolGroup.setToolDisabled(MIPJumpToClickTool.toolName) + } + }, + setFusionMipRotateEnabled(enabled) { + if (!this.isFusion) return + const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId) + if (!toolGroup || !toolGroup.hasTool(VolumeRotateTool.toolName)) return + if (enabled) { + toolGroup.setToolActive(VolumeRotateTool.toolName, { + bindings: [{ mouseButton: MouseBindings.Wheel }] + }) + } else { + toolGroup.setToolDisabled(VolumeRotateTool.toolName) + } + }, // 激活工具 setToolActive(toolName) { if (this.histogramVisible) return false - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return if (this.activeTool === toolName) { if (toolName === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) + this.setFusionMipJumpEnabled(true) + this.setFusionMipRotateEnabled(true) } else { toolGroup.setToolPassive(this.activeTool) } this.activeTool = '' } else { if (this.activeTool) { - if (toolName === CrosshairsTool.toolName) { + if (this.activeTool === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) + this.setFusionMipJumpEnabled(true) + this.setFusionMipRotateEnabled(true) } else { toolGroup.setToolPassive(this.activeTool) } @@ -2511,9 +2570,56 @@ export default { toolGroup.setToolActive(toolName, { bindings: [{ mouseButton: MouseBindings.Primary }] }) + if (toolName === CrosshairsTool.toolName) { + if (this.isFusion) { + const instance = toolGroup.getToolInstance?.(CrosshairsTool.toolName) + if (instance && !instance.__fusionSameForPatched) { + instance.__fusionSameForPatched = true + const original = instance._checkIfViewportsRenderingSameScene?.bind(instance) + instance._checkIfViewportsRenderingSameScene = (viewport, otherViewport) => { + try { + const a = viewport?.getFrameOfReferenceUID?.() + const b = otherViewport?.getFrameOfReferenceUID?.() + if (a && b && a === b) return true + } catch (e) {} + return original ? original(viewport, otherViewport) : true + } + } + } + this.setFusionMipJumpEnabled(false) + this.setFusionMipRotateEnabled(false) + } this.activeTool = toolName } }, + hoverFusionViewport(index) { + if (!this.isFusion) return + if (this.activeTool === CrosshairsTool.toolName) return + const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId) + if (!toolGroup) return + + const isMip = index === 3 + this.setFusionMipJumpEnabled(isMip) + if (isMip) { + if (toolGroup.hasTool(StackScrollTool.toolName)) { + toolGroup.setToolDisabled(StackScrollTool.toolName) + } + if (toolGroup.hasTool(VolumeRotateTool.toolName)) { + toolGroup.setToolActive(VolumeRotateTool.toolName, { + bindings: [{ mouseButton: MouseBindings.Wheel }] + }) + } + } else { + if (toolGroup.hasTool(VolumeRotateTool.toolName)) { + toolGroup.setToolDisabled(VolumeRotateTool.toolName) + } + if (toolGroup.hasTool(StackScrollTool.toolName)) { + toolGroup.setToolActive(StackScrollTool.toolName, { + bindings: [{ mouseButton: MouseBindings.Wheel }] + }) + } + } + }, // 激活标注工具 setAnnotateToolActive(toolName) { // if (this.readingTaskState === 2) return @@ -2522,8 +2628,9 @@ export default { if (!toolObj || toolObj.isDisabled) return const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return if (this.activeTool === toolName) { if (toolName === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) @@ -2554,8 +2661,9 @@ export default { if (this.activeTool === toolName) return const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return if (this.activeTool) { if (this.activeTool === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) @@ -2574,8 +2682,9 @@ export default { if (this.activeTool && this.toolNames.includes(this.activeTool)) { const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return if (this.activeTool === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) } else { @@ -2591,8 +2700,9 @@ export default { this.setToolsPassive() const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return toolGroup.setToolActive(toolName, { bindings: [{ mouseButton: MouseBindings.Primary }] }) @@ -2601,13 +2711,10 @@ export default { }, setToolsPassive() { if (!this.activeTool) return - let toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`] - if (this.isMPR) { - // toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`] - toolGroupIds = [this.volumeToolGroupId] - } + const toolGroupIds = this.getCurrentToolGroupIds() toolGroupIds.forEach(toolGroupId => { const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return if (this.activeTool === CrosshairsTool.toolName) { toolGroup.setToolDisabled(this.activeTool) } else { @@ -2618,13 +2725,10 @@ export default { }, setToolEnabled() { if (!this.activeTool) return - let toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`] - if (this.isMPR) { - // toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`] - toolGroupIds = [this.volumeToolGroupId] - } + const toolGroupIds = this.getCurrentToolGroupIds() toolGroupIds.forEach(toolGroupId => { const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return toolGroup.setToolEnabled(this.activeTool) }) this.activeTool = '' @@ -3217,7 +3321,9 @@ export default { DicomEvent.$emit('SegmentationLoading', `${this.viewportKey}-${this.activeViewportIndex}`) }) } - this.setToolsPassive() + if (this.activeTool !== CrosshairsTool.toolName) { + this.setToolsPassive() + } }, getRelatedSeries(visitTaskInfo, baselineSeries) { let obj = {} @@ -3582,8 +3688,9 @@ export default { this.setToolsPassive() } - const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroupId = this.getActiveToolGroupId() const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (!toolGroup) return toolGroup.setToolActive(toolName, { bindings: [{ mouseButton: MouseBindings.Primary }] }) @@ -3943,6 +4050,7 @@ export default { this.$refs[`viewport-fusion-1`][0].setSeriesInfo(ptData, false, { colorMap: false }) this.$refs[`viewport-fusion-2`][0].setSeriesInfo(fusionData, false, { isFusion: true, colorMap: true }) this.$refs[`viewport-fusion-3`][0].setSeriesInfo(ptData, false, { isMip: true, colorMap: false }) + await this.initFusionHiddenSagViewport(pt) // this.resetAnnotation = false this.$nextTick(() => { this.$refs[`colorMap`].init() @@ -3973,6 +4081,18 @@ export default { } return false }, + async initFusionHiddenSagViewport(pt) { + const ptVolumeId = pt?.SeriesInstanceUid + if (!ptVolumeId || !cache.getVolume(ptVolumeId)) return + const renderingEngine = getRenderingEngine(this.renderingEngineId) + const sagViewport = renderingEngine?.getViewport?.('viewport-fusion-hidden-sag') + if (!sagViewport) return + + await sagViewport.setVolumes([{ volumeId: ptVolumeId }]) + const midIndex = Math.max(0, Math.floor((pt.ImageIds?.length || 1) / 2)) + await csUtils.jumpToSlice(sagViewport.element, { imageIndex: midIndex }) + sagViewport.render() + }, async getVolume(serie, isFusion = false) { return new Promise(async res => { let volumeId = `${isFusion ? 'fusion_' : ''}` + serie.SeriesInstanceUid; @@ -4463,6 +4583,22 @@ export default { position: relative; } + .fusion-hidden-viewports { + position: absolute; + left: -100000px; + top: -100000px; + width: 512px; + height: 512px; + overflow: hidden; + opacity: 0; + pointer-events: none; + } + + .fusion-hidden-viewport { + width: 512px; + height: 512px; + } + .viewports-box { display: grid; position: absolute;