diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue index 22010f45..1a292bfc 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue @@ -179,17 +179,18 @@ + :measure-datas="measureDatas" :style="1 === activeIndex ? viewportStyle : {}" + @fusionSlicePointChange="handleFusionSlicePointChange" /> + @upperRangeChange="upperRangeChange" @fusionSlicePointChange="handleFusionSlicePointChange" /> + @upperRangeChange="upperRangeChange" @fusionSlicePointChange="handleFusionSlicePointChange" /> { - this.dispatchFusionCenterPoint(retryCount + 1) - }, 120) - } - return - } - - const candidates = [viewportIds.FUSION.AXIAL, viewportIds.PT.AXIAL, viewportIds.CT.AXIAL] - for (const viewportId of candidates) { - const viewport = renderEngine.getViewport(viewportId) - if (!viewport) continue - const width = viewport.element?.clientWidth - const height = viewport.element?.clientHeight - let worldPoint = null - if (width && height && viewport.canvasToWorld) { - worldPoint = viewport.canvasToWorld([width / 2, height / 2]) - } - if ((!worldPoint || worldPoint.length < 3) && viewport.getCamera) { - worldPoint = viewport.getCamera()?.focalPoint - } - if (!worldPoint || worldPoint.length < 3) continue - instance.setPoint(worldPoint, viewportId, renderEngine.id, { - jumpToTargetViewports: true, - dispatchEvent: false, - }) - return - } - if (retryCount < 10) { - setTimeout(() => { - this.dispatchFusionCenterPoint(retryCount + 1) - }, 120) - } - }, + getFusionJumpToolConfiguration() { + return { + targetViewportIds: [ + viewportIds.CT.AXIAL, + viewportIds.PT.AXIAL, + viewportIds.FUSION.AXIAL, + viewportIds.PETMIP.CORONAL + ], + useBrightestPoint: true, + jumpToTargetViewports: true, + dispatchEventName: 'fusion-mip-point-selected', + getReferenceLineColor: this.setFusionCrosshairsToolLineColor, + style: this.fusionCrosshairStyle, + referenceLinesCenterGapRadius: this.fusionCrosshairStyle.centerHoleSize, + minimal: { + enabled: true, + lineLengthInPx: this.fusionCrosshairStyle.lineLength, + }, + mipViewportIds: [viewportIds.PETMIP.CORONAL] + } + }, + setFusionCrosshairsToolLineColor(viewportId) { + const colors = { + [viewportIds.CT.AXIAL]: '#0000ff', + [viewportIds.PT.AXIAL]: '#0000ff', + [viewportIds.FUSION.AXIAL]: '#0000ff', + [viewportIds.PETMIP.CORONAL]: '#ff0000' + } + return colors[viewportId] || '#0000ff' + }, + handleFusionSlicePointChange({ viewportId, worldPoint }) { + if (!this.isFusion) return + if (!viewportId || !Array.isArray(worldPoint) || worldPoint.length < 3) return + if (viewportId === viewportIds.PETMIP.CORONAL) return + + const activeViewportId = this.activeIndex === 1 + ? viewportIds.CT.AXIAL + : this.activeIndex === 2 + ? viewportIds.PT.AXIAL + : this.activeIndex === 3 + ? viewportIds.FUSION.AXIAL + : viewportIds.PETMIP.CORONAL + if (viewportId !== activeViewportId) return + + const renderEngine = getRenderingEngine(renderingEngineId) + if (!renderEngine) return + const toolGroupCandidates = [fusionToolGroupId, mipToolGroupUID, ptToolGroupId, ctToolGroupId] + let instance = null + for (const toolGroupId of toolGroupCandidates) { + const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + instance = toolGroup.getToolInstance(FusionJumpToPointTool.toolName) + if (instance.setPoint) break + } + if (!instance.setPoint) return + + instance.setPoint(worldPoint, viewportId, renderEngine.id, { + jumpToTargetViewports: false, + dispatchEvent: false, + }) + }, + dispatchFusionCenterPoint(retryCount = 0) { + const renderEngine = getRenderingEngine(renderingEngineId) + if (!renderEngine) return + const toolGroupCandidates = [fusionToolGroupId, mipToolGroupUID, ptToolGroupId, ctToolGroupId] + let instance = null + for (const toolGroupId of toolGroupCandidates) { + const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + instance = toolGroup?.getToolInstance?.(FusionJumpToPointTool.toolName) + if (instance?.setPoint) break + } + if (!instance?.setPoint) { + if (retryCount < 10) { + setTimeout(() => { + this.dispatchFusionCenterPoint(retryCount + 1) + }, 120) + } + return + } + + const candidates = [viewportIds.FUSION.AXIAL, viewportIds.PT.AXIAL, viewportIds.CT.AXIAL] + for (const viewportId of candidates) { + const viewport = renderEngine.getViewport(viewportId) + if (!viewport) continue + const width = viewport.element?.clientWidth + const height = viewport.element?.clientHeight + let worldPoint = null + if (width && height && viewport.canvasToWorld) { + worldPoint = viewport.canvasToWorld([width / 2, height / 2]) + } + if ((!worldPoint || worldPoint.length < 3) && viewport.getCamera) { + worldPoint = viewport.getCamera()?.focalPoint + } + if (!worldPoint || worldPoint.length < 3) continue + instance.setPoint(worldPoint, viewportId, renderEngine.id, { + jumpToTargetViewports: true, + dispatchEvent: false, + }) + return + } + if (retryCount < 10) { + setTimeout(() => { + this.dispatchFusionCenterPoint(retryCount + 1) + }, 120) + } + }, getTextLines(data, targetId) { const cachedVolumeStats = data.cachedStats[targetId] const { diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/Viewport.vue b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/Viewport.vue index 2e38d02c..83339788 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/Viewport.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/Viewport.vue @@ -272,6 +272,24 @@ export default { this.renderColorBar(this.presetName) } } + + if (this.index !== 4 && viewport) { + const width = viewport.element.clientWidth + const height = viewport.element.clientHeight + let worldPoint = null + if (width && height && viewport.canvasToWorld) { + worldPoint = viewport.canvasToWorld([width / 2, height / 2]) + } + if ((!worldPoint || worldPoint.length < 3) && viewport.getCamera) { + worldPoint = viewport.getCamera()?.focalPoint + } + if (Array.isArray(worldPoint) && worldPoint.length >= 3) { + this.$emit('fusionSlicePointChange', { + viewportId: this.viewportId, + worldPoint: [...worldPoint] + }) + } + } }, getOrientationMarker() { // eslint-disable-next-line no-unused-vars 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 a4aa5c11..3f0b9ebc 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue @@ -270,6 +270,24 @@ export default { } } + if (!this.isMip && viewport) { + const width = this.element?.clientWidth + const height = this.element?.clientHeight + let worldPoint = null + if (width && height && viewport.canvasToWorld) { + worldPoint = viewport.canvasToWorld([width / 2, height / 2]) + } + if ((!worldPoint || worldPoint.length < 3) && viewport.getCamera) { + worldPoint = viewport.getCamera()?.focalPoint + } + if (Array.isArray(worldPoint) && worldPoint.length >= 3) { + this.$emit('fusionSlicePointChange', { + viewportId: this.viewportId, + worldPoint: [...worldPoint], + }) + } + } + }, setFullScreen(index) { setTimeout(() => { 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 a4e18cea..0cc92fc2 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -362,7 +362,7 @@ :viewport-index="index" :active-tool="activeTool" @activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD" @renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange" - @contentMouseup="contentMouseup" /> + @contentMouseup="contentMouseup" @fusionSlicePointChange="handleFusionSlicePointChange" />
@@ -2634,6 +2634,25 @@ export default { if (this.isFusion) return [this.fusionToolGroupId] return [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`] }, + handleFusionSlicePointChange({ viewportId, worldPoint }) { + if (!this.isFusion) return + if (!viewportId || !Array.isArray(worldPoint) || worldPoint.length < 3) return + + const activeFusionViewportId = `viewport-fusion-${this.activeViewportIndex}` + if (viewportId !== activeFusionViewportId) return + if (viewportId === 'viewport-fusion-3') return + + const renderingEngine = getRenderingEngine(renderingEngineId) + if (!renderingEngine) return + const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId) + const instance = toolGroup.getToolInstance(FusionJumpToPointTool.toolName) + if (!instance.setPoint) return + + instance.setPoint(worldPoint, viewportId, renderingEngine.id, { + jumpToTargetViewports: false, + dispatchEvent: false, + }) + }, setFusionMipJumpEnabled(enabled) { if (!this.isFusion) return const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId)