From aae5968d74ccbd92af857eeb0f9d73924407800b Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Mon, 30 Mar 2026 14:13:52 +0800 Subject: [PATCH] =?UTF-8?q?nm/ct=E8=9E=8D=E5=90=88=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dicoms3D/components/PetCtViewport.vue | 43 +++++++++++------ ...nColorMapTransferFunctionForVolumeActor.js | 46 +++++++++++++++++++ 2 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 src/views/trials/trials-panel/reading/dicoms3D/components/helpers/setNmFusionColorMapTransferFunctionForVolumeActor.js 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 ab408feb..acf7dbf0 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue @@ -5,7 +5,7 @@ :style="{ color: series.Modality === 'PT' || series.Modality === 'NM' || isMip ? '#666' : '#ddd' }">
{{ Math.round(fusionOpacity * 100) }}%
-
@@ -104,6 +104,7 @@ import { setMipTransferFunctionForVolumeActor, setPetTransferFunctionForVolumeActor } from './helpers/index.js' +import setNmFusionColorMapTransferFunctionForVolumeActor from './helpers/setNmFusionColorMapTransferFunctionForVolumeActor' const { BlendModes, OrientationAxis } = Enums; const { getColormap } = csUtils.colormap; import { vec3, mat4 } from 'gl-matrix' @@ -173,7 +174,7 @@ export default { ptVolumeId: null, loading: false, Colorbar: null, - fusionOpacity: 0.5, + fusionOpacity: 0.95, topFusionVolumeActor: null, currentVoiUpper: null } @@ -278,13 +279,13 @@ export default { } if (properties && properties.voiRange) { var { lower, upper } = properties.voiRange - if ((!upper || upper === 0) && this.currentVoiUpper > 0) { + if ((!upper || upper < 1) && this.currentVoiUpper >= 1) { upper = this.currentVoiUpper } else if (upper) { this.currentVoiUpper = upper } - if (!upper) return + if (!upper || upper < 1) return const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel( lower, @@ -554,7 +555,17 @@ export default { const ptFusionEntry = { volumeId: ptFusionVolumeId, callback: (r) => { - setPetColorMapTransferFunctionForVolumeActor({ ...r, volumeId: ptFusionVolumeId }) + if (this.series.Modality === 'NM') { + setNmFusionColorMapTransferFunctionForVolumeActor({ + ...r, + volumeId: ptFusionVolumeId, + }) + } else { + setPetColorMapTransferFunctionForVolumeActor({ + ...r, + volumeId: ptFusionVolumeId, + }) + } if (!this.fusionCtOnTop) { this.topFusionVolumeActor = r.volumeActor } @@ -564,14 +575,20 @@ export default { } const volumes = [] - if (this.series.Modality !== 'NM') { - volumes.push({ - volumeId: this.volumeId, - callback: (r) => { - console.log("融合pet渲染成功"); - } - }) - } + // if (this.series.Modality !== 'NM') { + // volumes.push({ + // volumeId: this.volumeId, + // callback: (r) => { + // console.log("融合pet渲染成功"); + // } + // }) + // } + volumes.push({ + volumeId: this.volumeId, + callback: (r) => { + console.log("融合pet渲染成功"); + } + }) if (this.fusionCtOnTop) { volumes.push(ptFusionEntry, ctEntry) diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/helpers/setNmFusionColorMapTransferFunctionForVolumeActor.js b/src/views/trials/trials-panel/reading/dicoms3D/components/helpers/setNmFusionColorMapTransferFunctionForVolumeActor.js new file mode 100644 index 00000000..3a0433ab --- /dev/null +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/helpers/setNmFusionColorMapTransferFunctionForVolumeActor.js @@ -0,0 +1,46 @@ +import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction"; +import vtkPiecewiseFunction from "@kitware/vtk.js/Common/DataModel/PiecewiseFunction"; +import { cache, metaData, utilities } from "@cornerstonejs/core"; + +const { getColormap } = utilities.colormap; + +function getWindowCenterFromVolumeId(volumeId) { + if (!volumeId) return null; + const imageVolume = cache.getVolume?.(volumeId); + const imageId = imageVolume?.imageIds?.[0]; + if (!imageId) return null; + const voiLutModule = metaData.get("voiLutModule", imageId); + const rawCenter = Array.isArray(voiLutModule?.windowCenter) + ? voiLutModule.windowCenter[0] + : voiLutModule?.windowCenter; + const center = Number(rawCenter); + return Number.isFinite(center) ? center : null; +} + +export default function setPetColorMapTransferFunctionForVolumeActor({ + volumeActor, + volumeId, + preset, +}) { + const mapper = volumeActor.getMapper?.(); + if (mapper?.setSampleDistance) { + mapper.setSampleDistance(1.0); + } + + const cfun = vtkColorTransferFunction.newInstance(); + const presetToUse = preset || getColormap("siemens"); + cfun.applyColorMap(presetToUse); + + const center = getWindowCenterFromVolumeId(volumeId); + const upper = Number.isFinite(center) && center > 1 ? center : 5; + cfun.setMappingRange(1, upper); + + volumeActor.getProperty().setRGBTransferFunction(0, cfun); + + const ofun = vtkPiecewiseFunction.newInstance(); + const rampX = Number.isFinite(upper) && upper > 0 ? Math.min(0.1, upper * 0.02) : 0.1; + ofun.addPoint(0, 0.0); + ofun.addPoint(rampX, 0.9); + ofun.addPoint(upper, 1.0); + volumeActor.getProperty().setScalarOpacity(0, ofun); +}