融合视口添加crosshairsTool工具

uat_us
caiyiling 2026-04-16 10:02:06 +08:00
parent 7001bc9ec0
commit cb04be1b56
2 changed files with 185 additions and 36 deletions

View File

@ -123,6 +123,10 @@ export default {
type: Number,
required: true
},
activeTool: {
type: String,
default: ''
},
},
data() {
return {
@ -254,10 +258,15 @@ 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)
const toolGroup =
cornerstoneTools.ToolGroupManager.getToolGroupForViewport(
this.viewportId,
this.renderingEngineId
) || cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId)
if (toolGroup) {
toolGroup.setToolEnabled('ScaleOverlay')
}
}
},
setFullScreen(index) {
@ -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

View File

@ -180,6 +180,11 @@
@click.prevent="openFusion">
<svg-icon icon-class="fusion" class="svg-icon" />
</div>
<div :class="['tool-item', activeTool === 'Crosshairs' ? 'tool-item-active' : '']"
v-if="readingTool === 2 && isFusion" :title="$t('trials:reading:button:crosshairs')"
@click.prevent="setToolActive('Crosshairs')">
<svg-icon icon-class="crosshairs" class="svg-icon" />
</div>
<div v-for="tool in tools" :key="tool.toolName"
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === tool.toolName ? 'tool-item-active' : '']"
:style="{ cursor: tool.isDisabled ? 'not-allowed' : 'pointer' }"
@ -349,15 +354,19 @@
:style="gridStyle">
<div v-for="(v, index) in cellsMax" v-show="index < cells.length" :key="`viewport-fusion-${index}`"
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)"
@mouseenter="hoverFusionViewport(index)" @mouseleave="hoverFusionViewport(-1)">
<PetCtViewport :ref="`viewport-fusion-${index}`" :data-viewport-uid="`viewport-fusion-${index}`"
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-fusion-${index}`"
:viewport-index="index" @activeViewport="activeViewport"
:viewport-index="index" :active-tool="activeTool" @activeViewport="activeViewport"
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
@renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange"
@contentMouseup="contentMouseup" />
</div>
</div>
<div v-if="readingTool === 2" class="fusion-hidden-viewports">
<div ref="viewport-fusion-hidden-sag" class="fusion-hidden-viewport" />
</div>
</div>
</div>
<!-- 表单 -->
@ -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)
}
@ -1615,17 +1642,10 @@ export default {
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}`)
})
}
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;