@@ -22,29 +22,13 @@
{{ ctSeries.Modality }} / {{ series.Modality }}
MIP
+ {{ fusionCtOnTop ? `${ctSeries.Modality}/${series.Modality}` : `${series.Modality}/${ctSeries.Modality}` }}
+
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
@@ -111,7 +95,7 @@ import {
import * as cornerstoneTools from '@cornerstonejs/tools'
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
-import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction'
+
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
@@ -146,6 +130,7 @@ export default {
petSeries: {},
isFusion: false,
isMip: false,
+ fusionCtOnTop: false,
taskInfo: null,
sliderInfo: {
oldB: null,
@@ -185,9 +170,10 @@ export default {
},
ptVolumeId: null,
loading: false,
-Colorbar: null,
- nmOpacity: 0.6,
- nmFusionVolumeActor: null
+ Colorbar: null,
+ fusionOpacity: 0.5,
+ topFusionVolumeActor: null,
+ currentVoiUpper: null
}
},
mounted() {
@@ -288,6 +274,14 @@ Colorbar: null,
}
if (properties && properties.voiRange) {
var { lower, upper } = properties.voiRange
+ if ((!upper || upper === 0) && this.currentVoiUpper > 0) {
+ upper = this.currentVoiUpper
+ } else if (upper) {
+ this.currentVoiUpper = upper
+ }
+
+ if (!upper) return
+
const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
lower,
upper
@@ -296,6 +290,9 @@ Colorbar: null,
if (this.series.Modality === 'PT' || this.series.Modality === 'NM' || this.isFusion) {
this.$emit('upperRangeChange', Math.round(upper))
}
+ if (this.isFusion && !this.fusionCtOnTop && this.topFusionVolumeActor) {
+ this.applyFusionOpacity()
+ }
}
},
getOrientationMarker() {
@@ -416,6 +413,11 @@ Colorbar: null,
voiChange(v) {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const voiRange = { lower: 0, upper: v }
+ this.currentVoiUpper = v
+ if (this.isFusion) {
+ console.log('voiChange', v)
+ }
+
const viewport = renderingEngine.getViewport(this.viewportId)
if (!viewport) return
let volumeId = this.isFusion ? this.ptVolumeId : this.volumeId
@@ -425,6 +427,11 @@ Colorbar: null,
)
viewport.setProperties({ voiRange }, volumeId)
+
+ // if (this.isFusion && !this.fusionCtOnTop && this.topFusionVolumeActor) {
+ // this.applyFusionOpacity()
+ // }
+
viewportsContainingVolumeUID.forEach((vp) => {
vp.render()
// this.$refs[vp.id].voiModified()
@@ -464,17 +471,21 @@ Colorbar: null,
ctx.fillStyle = gradient
ctx.fillRect(0, 0, rectWidth, rectHeight)
},
- applyNmOpacity() {
- if (!this.nmFusionVolumeActor?.getProperty) {
- return;
- }
- const ofun = vtkPiecewiseFunction.newInstance();
- ofun.addPoint(0, 0.0);
- ofun.addPoint(0.1, 0.9 * this.nmOpacity);
- ofun.addPoint(5, 1.0 * this.nmOpacity);
- this.nmFusionVolumeActor.getProperty().setScalarOpacity(0, ofun);
+ opacityChange(opacity) {
+ this.fusionOpacity = opacity
const renderingEngine = getRenderingEngine(this.renderingEngineId)
- renderingEngine?.render?.();
+ const viewport = renderingEngine.getViewport(this.viewportId)
+ if (!viewport) return
+ let volumeId = this.isFusion ? this.ptVolumeId : this.volumeId
+
+ viewport.setProperties(
+ { colormap: { opacity: Number(opacity) } },
+ volumeId
+ )
+ viewport.render()
+ },
+ applyFusionOpacity() {
+ this.opacityChange(this.fusionOpacity)
},
setPreset(presetName) {
this.presetName = presetName
@@ -507,6 +518,85 @@ Colorbar: null,
})
this.loading = false
},
+ getFusionVolumes() {
+ const ctVolumeId = this.ctSeries?.SeriesInstanceUid
+ const ptFusionVolumeId = this.ptVolumeId
+ if (!ctVolumeId || !ptFusionVolumeId) {
+ return []
+ }
+
+ const ctEntry = {
+ volumeId: ctVolumeId,
+ callback: (r) => {
+ setCtTransferFunctionForVolumeActor({ ...r, volumeId: ctVolumeId })
+ if (this.fusionCtOnTop) {
+ this.topFusionVolumeActor = r.volumeActor
+ this.applyFusionOpacity()
+ }
+ console.log("融合ct渲染成功")
+ }
+ }
+
+ const ptFusionEntry = {
+ volumeId: ptFusionVolumeId,
+ callback: (r) => {
+ setPetColorMapTransferFunctionForVolumeActor({ ...r, volumeId: ptFusionVolumeId })
+ if (!this.fusionCtOnTop) {
+ this.topFusionVolumeActor = r.volumeActor
+ this.applyFusionOpacity()
+ }
+ console.log("融合pet渲染成功")
+ }
+ }
+
+ const volumes = []
+ if (this.series.Modality !== 'NM') {
+ volumes.push({
+ volumeId: this.volumeId,
+ callback: (r) => {
+ console.log("融合pet渲染成功");
+ }
+ })
+ }
+
+ if (this.fusionCtOnTop) {
+ volumes.push(ptFusionEntry, ctEntry)
+ } else {
+ volumes.push(ctEntry, ptFusionEntry)
+ }
+
+ return volumes
+ },
+ async applyFusionRenderOrder() {
+ if (!this.isFusion) return
+ const renderingEngine = getRenderingEngine(this.renderingEngineId)
+ const viewport = renderingEngine?.getViewport?.(this.viewportId)
+ if (!viewport) return
+
+ const volumes = this.getFusionVolumes()
+ if (!volumes.length) return
+
+ const camera = viewport.getCamera?.()
+
+ const savedVoiUpper = this.currentVoiUpper
+
+ await viewport.setVolumes(volumes)
+ if (camera) {
+ viewport.setCamera(camera)
+ }
+
+ if (savedVoiUpper) {
+ viewport.setProperties({ voiRange: { lower: 0, upper: savedVoiUpper } }, this.ptVolumeId)
+ }
+
+ viewport.render()
+ },
+ toggleFusionRenderOrder() {
+ if (!this.isFusion) return
+ this.fusionCtOnTop = !this.fusionCtOnTop
+ this.applyFusionRenderOrder()
+ this.$emit('upperRangeChange', Math.round(this.currentVoiUpper))
+ },
async setSeriesInfo(obj, isLocate = false, option = {}) {
try {
let { data } = obj
@@ -519,11 +609,12 @@ Colorbar: null,
this.volumeId = data.SeriesInstanceUid
this.ptVolumeId = null
this.series = {}
- this.nmFusionVolumeActor = null
+ this.topFusionVolumeActor = null
let { isFusion, isMip, colorMap } = option
this.isFusion = isFusion;
this.isMip = isMip;
if (this.isFusion) {
+ this.fusionCtOnTop = false
this.$nextTick(() => {
this.renderColorBar(this.presetName)
})
@@ -531,34 +622,10 @@ Colorbar: null,
let { ct, data } = obj
this.series = { ...data }
this.ctSeries = { ...ct }
- let volumes = [
- {
- volumeId: ct.SeriesInstanceUid, callback: (r) => {
- setCtTransferFunctionForVolumeActor(r)
- console.log("融合ct渲染成功")
- }
- },
- {
- volumeId: this.ptVolumeId, callback: (r) => {
- setPetColorMapTransferFunctionForVolumeActor(r)
- if (this.series.Modality === 'NM') {
- this.nmFusionVolumeActor = r.volumeActor
- this.applyNmOpacity()
- }
- console.log("融合pet渲染成功")
- }
- },
- ]
- if (this.series.Modality !== 'NM') {
- volumes.unshift({
- volumeId: this.volumeId, callback: (r) => {
- // setPetColorMapTransferFunctionForVolumeActor(r)
- console.log("融合pet渲染成功");
- }
- })
- }
- await viewport.setVolumes(volumes)
+
+
+ await viewport.setVolumes(this.getFusionVolumes())
} else {
this.series = { ...data }
if (this.isMip) {
@@ -593,9 +660,9 @@ Colorbar: null,
volumeId: this.volumeId, callback: (r) => {
if (this.series.Modality === 'PT' || this.series.Modality === 'NM') {
// setPetColorMapTransferFunctionForVolumeActor(r, true)
- setPetTransferFunctionForVolumeActor(r)
+ setPetTransferFunctionForVolumeActor({ ...r, volumeId: this.volumeId })
} else {
- setCtTransferFunctionForVolumeActor(r)
+ setCtTransferFunctionForVolumeActor({ ...r, volumeId: this.volumeId })
}
}
}])
@@ -603,6 +670,7 @@ Colorbar: null,
}
viewport.render()
+ this.voiChange(this.currentVoiUpper)
} catch (e) {
console.log(e)
}
@@ -782,7 +850,7 @@ Colorbar: null,
},
beforeDestroy() {
this.series = null
- this.nmFusionVolumeActor = null
+ this.topFusionVolumeActor = null
},
computed: {
NSTip() {
@@ -892,6 +960,20 @@ Colorbar: null,
font-size: 12px;
}
+ .fusion-order-toggle {
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ z-index: 2;
+ font-size: 12px;
+ padding: 2px 8px;
+ background: rgba(0, 0, 0, 0.35);
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ border-radius: 2px;
+ cursor: pointer;
+ user-select: none;
+ }
+
.left-bottom-text {
position: absolute;
left: 5px;
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 4ff9f2cd..005c2349 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
@@ -273,8 +273,12 @@
-
+
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/colorMap.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/colorMap.vue
index 703d6b50..ee58b425 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/colorMap.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/colorMap.vue
@@ -34,7 +34,7 @@