1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057 |
- import React, { useEffect, useRef } from 'react';
- import * as cornerstone from '@cornerstonejs/core';
- import type { Types } from '@cornerstonejs/core';
- import * as cornerstoneTools from '@cornerstonejs/tools';
- import { annotation, SplineROITool } from '@cornerstonejs/tools';
- import { eventTarget } from '@cornerstonejs/core';
- import { registerGlobalTools } from '@/utils/cornerstoneToolsSetup';
- import { MeasurementToolManager } from '@/utils/measurementToolManager';
- import TibialPlateauAngleTool from '@/components/measures/TibialPlateauAngleTool';
- import DARAMeasurementTool from '@/components/measures/DARAMeasurementTool';
- import HipDIMeasurementTool from '@/components/measures/HipDIMeasurementTool';
- import HipNHAAngleMeasurementTool from '@/components/measures/HipNHAAngleMeasurementTool';
- import VHSMeasurementTool from '@/components/measures/VHSMeasurementTool';
- import TPLOMeasurementTool from '@/components/measures/TPLOMeasurementTool';
- import { boolean } from 'zod';
- const {
- MagnifyTool,
- PanTool,
- WindowLevelTool,
- StackScrollTool,
- ZoomTool,
- LabelTool,
- LengthTool,
- AngleTool,//角度测量工具
- ToolGroupManager,
- Enums: csToolsEnums,
- PlanarRotateTool,
- } = cornerstoneTools;
- const { MouseBindings } = csToolsEnums;
- // let toolGroup: cornerstoneTools.Types.IToolGroup;
- // let currentViewportId: string;
- function getToolgroupByViewportId(currentViewportId: string) {
- const toolGroup = ToolGroupManager.getToolGroup(
- `STACK_TOOL_GROUP_ID_${currentViewportId}`
- );
- if (!toolGroup) {
- console.log('toolGroup not found');
- throw new Error('Tool group not found');
- }
- return toolGroup;
- }
- function overlayRedRectangle(currentViewportId: string) {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- const viewportElement = viewport.element;
- const annotations = cornerstoneTools.annotation.state.getAnnotations(
- 'LinearSplineROI',
- viewportElement
- );
- if (!annotations || annotations.length === 0) {
- console.log('No ROI annotations found');
- return;
- }
- const annotation = annotations[annotations.length - 1];
- const points = annotation?.data?.handles?.points;
- // 创建一个覆盖 Canvas
- const canvas = document.createElement('canvas');
- canvas.style.position = 'absolute';
- canvas.width = viewportElement.clientWidth;
- canvas.height = viewportElement.clientHeight;
- viewportElement.firstChild?.appendChild(canvas);
- const ctx = canvas.getContext('2d');
- if (!ctx) {
- throw new Error('Failed to get 2D context from canvas');
- }
- ctx.fillStyle = 'rgba(0, 0, 0, 1)';
- // 将 ROI 坐标转换为 Canvas 坐标
- if (!points) {
- console.log('No points found in handles');
- return;
- }
- // Convert all points to canvas coordinates
- const z = viewport.getCurrentImageIdIndex() || 0;
- const canvasPoints = points.map((point: Types.Point2 | Types.Point3) => {
- const point3D: Types.Point3 =
- point.length === 2 ? [point[0], point[1], z] : point;
- return viewport.worldToCanvas(point3D);
- });
- // Log for debugging
- console.log('Canvas Points:', canvasPoints);
- // Draw the polygon
- ctx.beginPath();
- ctx.rect(0, 0, canvas.width, canvas.height); // Full canvas for evenodd rule
- ctx.moveTo(canvasPoints[0][0], canvasPoints[0][1]); // Start at the first point
- for (let i = 1; i < canvasPoints.length; i++) {
- ctx.lineTo(canvasPoints[i][0], canvasPoints[i][1]); // Connect to subsequent points
- }
- ctx.closePath(); // Close the polygon
- ctx.fill('evenodd'); // Fill with red
- }
- function registerTools(viewportId, renderingEngineId) {
- // 确保全局工具已注册(只会执行一次)
- registerGlobalTools();
- // 创建该 viewport 的工具组
- const toolGroupId = `STACK_TOOL_GROUP_ID_${viewportId}`;
- const toolGroupTmp = ToolGroupManager.createToolGroup(toolGroupId);
- if (!toolGroupTmp) {
- console.error(
- `[registerTools] Failed to create tool group for viewport: ${viewportId}`
- );
- return;
- }
- const toolGroup = toolGroupTmp;
- // 添加工具到工具组
- toolGroup.addTool(MagnifyTool.toolName);
- toolGroup.addTool(PanTool.toolName);
- toolGroup.addTool(WindowLevelTool.toolName);
- toolGroup.addTool(StackScrollTool.toolName);
- toolGroup.addTool(ZoomTool.toolName);
- toolGroup.addTool(LabelTool.toolName);
- toolGroup.addTool(PlanarRotateTool.toolName);
- toolGroup.addTool(LengthTool.toolName); // 添加线段测量工具
- toolGroup.addTool(AngleTool.toolName); // 添加角度测量工具
- toolGroup.addTool(TibialPlateauAngleTool.toolName); // 添加胫骨平台夹角测量工具
- toolGroup.addTool(DARAMeasurementTool.toolName); // 添加髋臼水平角测量工具
- toolGroup.addTool(HipDIMeasurementTool.toolName); // 添加髋关节牵引指数测量工具
- toolGroup.addTool(HipNHAAngleMeasurementTool.toolName); // 添加髋关节水平角测量工具
- toolGroup.addTool(VHSMeasurementTool.toolName); // 添加心锥比测量工具
- toolGroup.addTool(TPLOMeasurementTool.toolName); // 添加TPLO测量工具
- // 设置默认工具状态
- setupDefaultToolStates(toolGroup);
- // 添加 viewport 到工具组
- toolGroup.addViewport(viewportId, renderingEngineId);
- console.log(`[registerTools] Tools registered for viewport: ${viewportId}`);
- }
- /**
- * 设置默认工具状态
- */
- function setupDefaultToolStates(toolGroup: cornerstoneTools.Types.IToolGroup) {
- // 设置平移工具(中键)
- toolGroup.setToolActive(PanTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Auxiliary, // Middle Click
- },
- ],
- });
- // 设置缩放工具(右键)
- toolGroup.setToolActive(ZoomTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Secondary, // Right Click
- },
- ],
- });
- // 设置滚轮滚动工具
- toolGroup.setToolActive(StackScrollTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Wheel, // Mouse Wheel
- },
- ],
- });
- // 其他工具默认为被动状态
- toolGroup.setToolPassive(MagnifyTool.toolName);
- toolGroup.setToolPassive(WindowLevelTool.toolName);
- toolGroup.setToolPassive(LabelTool.toolName);
- toolGroup.setToolPassive(PlanarRotateTool.toolName);
- toolGroup.setToolPassive(LengthTool.toolName);
- toolGroup.setToolPassive(AngleTool.toolName);
- toolGroup.setToolPassive(TibialPlateauAngleTool.toolName);
- toolGroup.setToolPassive(DARAMeasurementTool.toolName);
- toolGroup.setToolPassive(HipDIMeasurementTool.toolName);
- toolGroup.setToolPassive(HipNHAAngleMeasurementTool.toolName);
- toolGroup.setToolPassive(VHSMeasurementTool.toolName);
- toolGroup.setToolPassive(TPLOMeasurementTool.toolName);
- }
- export function addLMark(currentViewportId: string): void {
- // Implement the logic to add an L mark
- console.log('Adding L Mark viewport id : ', currentViewportId);
- const toolGroup = getToolgroupByViewportId(currentViewportId);
- // currentViewportId = viewportId;
- toolGroup.setToolActive(LabelTool.toolName, {
- bindings: [
- // {
- // mouseButton: MouseBindings.Primary, // Left Click
- // },
- ],
- });
- const position: Types.Point3 = [100, 100, 0]; // Example position
- const text = 'L'; // Predefined text
- LabelTool.hydrate(currentViewportId, position, text);
- toolGroup.setToolPassive(LabelTool.toolName, {
- removeAllBindings: true,
- });
- // const enabledElement = cornerstone.getEnabledElementByViewportId(currentViewportId);
- // cursors.elementCursor.resetElementCursor(elementRef.current as HTMLDivElement);
- }
- export function addRLabel(viewportId) {
- const toolGroup = getToolgroupByViewportId(viewportId);
- toolGroup.setToolActive(LabelTool.toolName, {
- bindings: [],
- });
- const element = document.getElementById(viewportId);
- const elementHeight = element ? element.getBoundingClientRect().height : 0;
- const position: Types.Point3 = [100, elementHeight / 2, 0]; // Example position
- const text = 'R'; // Predefined text
- LabelTool.hydrate(viewportId, position, text);
- toolGroup.setToolPassive(LabelTool.toolName, { removeAllBindings: true });
- }
- export function adjustBrightnessAndContrast(currentViewportId: string) {
- const toolGroup = getToolgroupByViewportId(currentViewportId);
- const planar = toolGroup.getToolInstance(WindowLevelTool.toolName); // Reset rotation angle
- const isActive = planar.mode === csToolsEnums.ToolModes.Active;
- if (isActive) {
- toolGroup.setToolPassive(WindowLevelTool.toolName, {
- removeAllBindings: true,
- });
- } else {
- toolGroup.setToolActive(WindowLevelTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Primary, // Left Click
- },
- ],
- });
- }
- }
- export function fitImageSize(currentViewportId: string) {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- viewport.resetCamera();
- viewport.render();
- }
- export function deleteSelectedMark(currentViewportId: string): void {
- const viewport =
- cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
- const allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();
- for (const annotation of allAnnotations) {
- if (annotation.data.text === 'L' || annotation.data.text === 'R') {
- cornerstoneTools.annotation.state.removeAnnotation(
- annotation.annotationUID!
- );
- }
- }
- viewport.render();
- }
- export function addMask(currentViewportId: string): void {
- // Implement the logic to add a mask
- console.log('Adding Mask');
- // Add the specific logic to add a mask here
- cornerstoneTools.addTool(SplineROITool);
- const toolGroup = getToolgroupByViewportId(currentViewportId);
- toolGroup.addTool(SplineROITool.toolName);
- toolGroup.addToolInstance('LinearSplineROI', SplineROITool.toolName, {
- spline: {
- type: SplineROITool.SplineTypes.Linear,
- },
- });
- toolGroup.setToolActive('LinearSplineROI', {
- bindings: [{ mouseButton: MouseBindings.Primary }],
- });
- }
- export function remoteMask(currentViewportId: string): void {
- // 1. 获取所有 annotation
- const all = annotation.state.getAllAnnotations();
- // 2. 过滤出 LinearSplineROI 产生的
- const toRemove = all.filter(
- (a) => a.metadata?.toolName === 'LinearSplineROI'
- );
- // 3. 逐条删掉
- toRemove.forEach((a) => {
- if (a.annotationUID) {
- annotation.state.removeAnnotation(a.annotationUID);
- }
- });
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- viewport.render();
- console.log('Deleting Digital Mask');
- const viewportElement = viewport.element;
- const firstChild = viewportElement.firstChild;
- if (firstChild) {
- const canvasElements = Array.from(firstChild.childNodes).filter(
- (child): child is Element =>
- child instanceof Element && child.tagName === 'CANVAS'
- );
- canvasElements.slice(1).forEach((canvas) => {
- firstChild.removeChild(canvas);
- });
- }
- }
- export function HorizontalFlip(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // 切换水平翻转状态
- const { flipHorizontal } = viewport.getCamera();
- viewport.setCamera({ flipHorizontal: !flipHorizontal });
- console.log('Flipping Image Horizontally');
- }
- export function VerticalFlip(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // 切换竖直翻转状态
- const { flipVertical } = viewport.getCamera();
- viewport.setCamera({ flipVertical: !flipVertical });
- }
- export function ApplyColormap(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // Implement the logic to apply colormap
- viewport.setProperties({ colormap: { name: 'hsv' } });
- viewport.render();
- console.log('Applying Colormap');
- }
- export function RotateCounterclockwise90(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // 获取当前相机
- const camera = viewport.getCamera();
- // 计算新的旋转角度(当前角度 + 90度)
- const newRotation = (camera.rotation ?? 0) + 90;
- // 但计算viewUp向量时,我们应该使用90度的弧度,而不是新角度的弧度!
- const ninetyDegreesRadians = (90 * Math.PI) / 180;
- // 获取当前的viewUp向量
- const currentViewUp = camera.viewUp || [0, 1, 0];
- // 计算旋转后的viewUp向量(这才是正确的相对旋转)
- const newViewUp: [number, number, number] = [
- currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
- currentViewUp[1] * Math.sin(ninetyDegreesRadians),
- currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
- currentViewUp[1] * Math.cos(ninetyDegreesRadians),
- 0,
- ];
- // 设置新的相机参数
- viewport.setCamera({
- ...camera,
- viewUp: newViewUp,
- rotation: newRotation % 360, // 确保角度在0-359范围内
- });
- viewport.render();
- console.log('Rotating Image Counterclockwise 90°');
- }
- export function RotateClockwise90(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- const camera = viewport.getCamera();
- // 计算新的旋转角度(当前角度 + 90度)
- const newRotation = (camera.rotation ?? 0) - 90;
- // 但计算viewUp向量时,我们应该使用90度的弧度,而不是新角度的弧度!
- const ninetyDegreesRadians = (90 * Math.PI) / 180;
- // 获取当前的viewUp向量
- const currentViewUp = camera.viewUp || [0, 1, 0];
- // 计算旋转后的viewUp向量(这才是正确的相对旋转)
- const newViewUp: [number, number, number] = [
- currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
- currentViewUp[1] * Math.sin(ninetyDegreesRadians),
- currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
- currentViewUp[1] * Math.cos(ninetyDegreesRadians),
- 0,
- ];
- // 设置新的相机参数
- viewport.setCamera({
- ...camera,
- viewUp: newViewUp,
- rotation: newRotation % 360, // 确保角度在0-359范围内
- });
- viewport.render();
- console.log('Rotating Image Clockwise 90°');
- }
- export function ResetImage(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // Implement the logic to reset the image
- // Resets the viewport's camera
- viewport.resetCamera();
- // Resets the viewport's properties
- viewport.resetProperties();
- viewport.render();
- console.log('Resetting Image');
- }
- export function InvertImage(currentViewportId: string): void {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // Implement the logic to invert the image
- const invert = !viewport.getProperties().invert;
- viewport.setProperties({ invert });
- viewport.render();
- console.log('Inverting Image');
- }
- export function setOriginalSize(currentViewportId: string) {
- const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
- .viewport as cornerstone.StackViewport;
- // 1) 先正常 fit(或本来就是 fit 状态)
- viewport.resetCamera();
- // 2) 计算“fit → 1:1”的放大倍数
- const { dimensions, spacing } = viewport.getImageData();
- console.log(`dimensions:${dimensions}, spacing:${spacing}`);
- const canvas = viewport.canvas;
- // 水平方向 1:1 需要的倍率
- const cssPixelsPerDicomPx = canvas.clientWidth / (dimensions[0] * spacing[0]);
- // 垂直方向 1:1 需要的倍率
- const cssPixelsPerDicomPy =
- canvas.clientHeight / (dimensions[1] * spacing[1]);
- // 取两者最小值,保证整张图不会被裁剪
- const zoomFactor = Math.min(cssPixelsPerDicomPx, cssPixelsPerDicomPy);
- console.log(`zoomFactor:${zoomFactor}`);
- console.log(
- `canvas.clientWidth:${canvas.clientWidth}, dimensions[0]:${dimensions[0]}, spacing[0]:${spacing[0]}`
- );
- console.log(
- `canvas.clientHeight:${canvas.clientHeight}, dimensions[1]:${dimensions[1]}, spacing[1]:${spacing[1]}`
- );
- // 3) 直接放大
- const zoom = viewport.getZoom();
- viewport.setZoom((zoom * 1) / zoomFactor);
- viewport.render();
- }
- export function activateMagnifier(currentViewportId: string) {
- console.log('Activating Magnifier');
- const toolGroup = getToolgroupByViewportId(currentViewportId);
- const isActive =
- toolGroup.getActivePrimaryMouseButtonTool() === MagnifyTool.toolName;
- if (isActive) {
- toolGroup.setToolPassive(MagnifyTool.toolName, {
- removeAllBindings: true,
- });
- } else {
- toolGroup.setToolActive(MagnifyTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Primary, // Left Click
- },
- ],
- });
- }
- }
- export function invertContrast(currentViewportId: string) {
- const viewport =
- cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
- const targetBool = !viewport.getProperties().invert;
- viewport.setProperties({
- invert: targetBool,
- });
- viewport.render();
- }
- export function rotateAnyAngle(currentViewportId: string) {
- const toolGroup = getToolgroupByViewportId(currentViewportId);
- const planar = toolGroup.getToolInstance(PlanarRotateTool.toolName); // Reset rotation angle
- const isActive = planar.mode === csToolsEnums.ToolModes.Active;
- console.log(
- `PlanarRotateTool is currently ${isActive ? 'active' : 'inactive'}`
- );
- if (isActive) {
- toolGroup.setToolPassive(PlanarRotateTool.toolName, {
- removeAllBindings: true,
- });
- } else {
- toolGroup.setToolActive(PlanarRotateTool.toolName, {
- bindings: [
- {
- mouseButton: MouseBindings.Primary, // Left Click
- },
- ],
- });
- }
- console.log('Rotating Image by Any Angle');
- }
- // ==================== 线段测量相关函数 ====================
- /**
- * 激活线段测量工具
- */
- export function activateLengthMeasurement(viewportId: string): boolean {
- console.log(
- `[activateLengthMeasurement] Activating length measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateLengthTool(viewportId);
- }
- /**
- * 停用线段测量工具
- */
- export function deactivateLengthMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateLengthMeasurement] Deactivating length measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateLengthTool(viewportId);
- }
- /**
- * 切换线段测量工具状态
- */
- export function toggleLengthMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleLengthMeasurement] Toggling length measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleLengthTool(viewportId);
- }
- /**
- * 清除线段测量标注
- */
- export function clearLengthMeasurements(viewportId: string): boolean {
- console.log(
- `[clearLengthMeasurements] Clearing length measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearLengthMeasurements(viewportId);
- }
- /**
- * 获取线段测量结果
- */
- // eslint-disable-next-line
- export function getLengthMeasurements(viewportId: string): any[] {
- console.log(
- `[getLengthMeasurements] Getting length measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getLengthMeasurements(viewportId);
- }
- /**
- * 检查线段测量工具是否激活
- */
- export function isLengthMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isLengthToolActive(viewportId);
- }
- // ==================== 角度测量相关函数 ====================
- /**
- * 激活角度测量工具
- */
- export function activateAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[activateAngleMeasurement] Activating angle measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateAngleTool(viewportId);
- }
- /**
- * 停用角度测量工具
- */
- export function deactivateAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateAngleMeasurement] Deactivating angle measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateAngleTool(viewportId);
- }
- /**
- * 切换角度测量工具状态
- */
- export function toggleAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleAngleMeasurement] Toggling angle measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleAngleTool(viewportId);
- }
- /**
- * 清除角度测量标注
- */
- export function clearAngleMeasurements(viewportId: string): boolean {
- console.log(
- `[clearAngleMeasurements] Clearing angle measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearAngleMeasurements(viewportId);
- }
- /**
- * 获取角度测量结果
- */
- // eslint-disable-next-line
- export function getAngleMeasurements(viewportId: string): any[] {
- console.log(
- `[getAngleMeasurements] Getting angle measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getAngleMeasurements(viewportId);
- }
- /**
- * 检查角度测量工具是否激活
- */
- export function isAngleMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isAngleToolActive(viewportId);
- }
- // ==================== 胫骨平台夹角测量相关函数 ====================
- /**
- * 激活胫骨平台夹角测量工具
- */
- export function activateTibialPlateauAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[activateTibialPlateauAngleMeasurement] Activating TPA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateTibialPlateauAngleTool(viewportId);
- }
- /**
- * 停用胫骨平台夹角测量工具
- */
- export function deactivateTibialPlateauAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateTibialPlateauAngleMeasurement] Deactivating TPA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateTibialPlateauAngleTool(viewportId);
- }
- /**
- * 切换胫骨平台夹角测量工具状态
- */
- export function toggleTibialPlateauAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleTibialPlateauAngleMeasurement] Toggling TPA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleTibialPlateauAngleTool(viewportId);
- }
- /**
- * 清除胫骨平台夹角测量标注
- */
- export function clearTibialPlateauAngleMeasurements(viewportId: string): boolean {
- console.log(
- `[clearTibialPlateauAngleMeasurements] Clearing TPA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearTibialPlateauAngleMeasurements(viewportId);
- }
- /**
- * 获取胫骨平台夹角测量结果
- */
- // eslint-disable-next-line
- export function getTibialPlateauAngleMeasurements(viewportId: string): any[] {
- console.log(
- `[getTibialPlateauAngleMeasurements] Getting TPA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getTibialPlateauAngleMeasurements(viewportId);
- }
- /**
- * 检查胫骨平台夹角测量工具是否激活
- */
- export function isTibialPlateauAngleMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isTibialPlateauAngleToolActive(viewportId);
- }
- // ==================== 髋臼水平角测量相关函数 ====================
- /**
- * 激活髋臼水平角测量工具
- */
- export function activateDARAMeasurement(viewportId: string): boolean {
- console.log(
- `[activateDARAMeasurement] Activating DARA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateDARAMeasurementTool(viewportId);
- }
- /**
- * 停用髋臼水平角测量工具
- */
- export function deactivateDARAMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateDARAMeasurement] Deactivating DARA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateDARAMeasurementTool(viewportId);
- }
- /**
- * 切换髋臼水平角测量工具状态
- */
- export function toggleDARAMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleDARAMeasurement] Toggling DARA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleDARAMeasurementTool(viewportId);
- }
- /**
- * 清除髋臼水平角测量标注
- */
- export function clearDARAMeasurements(viewportId: string): boolean {
- console.log(
- `[clearDARAMeasurements] Clearing DARA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearDARAMeasurements(viewportId);
- }
- /**
- * 获取髋臼水平角测量结果
- */
- // eslint-disable-next-line
- export function getDARAMeasurements(viewportId: string): any[] {
- console.log(
- `[getDARAMeasurements] Getting DARA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getDARAMeasurements(viewportId);
- }
- /**
- * 检查髋臼水平角测量工具是否激活
- */
- export function isDARAMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isDARAMeasurementToolActive(viewportId);
- }
- // ==================== 髋关节牵引指数测量相关函数 ====================
- /**
- * 激活髋关节牵引指数测量工具
- */
- export function activateHipDIMeasurement(viewportId: string): boolean {
- console.log(
- `[activateHipDIMeasurement] Activating HipDI measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateHipDIMeasurementTool(viewportId);
- }
- /**
- * 停用髋关节牵引指数测量工具
- */
- export function deactivateHipDIMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateHipDIMeasurement] Deactivating HipDI measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateHipDIMeasurementTool(viewportId);
- }
- /**
- * 切换髋关节牵引指数测量工具状态
- */
- export function toggleHipDIMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleHipDIMeasurement] Toggling HipDI measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleHipDIMeasurementTool(viewportId);
- }
- /**
- * 清除髋关节牵引指数测量标注
- */
- export function clearHipDIMeasurements(viewportId: string): boolean {
- console.log(
- `[clearHipDIMeasurements] Clearing HipDI measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearHipDIMeasurements(viewportId);
- }
- /**
- * 获取髋关节牵引指数测量结果
- */
- // eslint-disable-next-line
- export function getHipDIMeasurements(viewportId: string): any[] {
- console.log(
- `[getHipDIMeasurements] Getting HipDI measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getHipDIMeasurements(viewportId);
- }
- /**
- * 检查髋关节牵引指数测量工具是否激活
- */
- export function isHipDIMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isHipDIMeasurementToolActive(viewportId);
- }
- // ==================== 髋关节水平角测量相关函数 ====================
- /**
- * 激活髋关节水平角测量工具
- */
- export function activateHipNHAAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[activateHipNHAAngleMeasurement] Activating HipNHA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateHipNHAAngleMeasurementTool(viewportId);
- }
- /**
- * 停用髋关节水平角测量工具
- */
- export function deactivateHipNHAAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateHipNHAAngleMeasurement] Deactivating HipNHA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateHipNHAAngleMeasurementTool(viewportId);
- }
- /**
- * 切换髋关节水平角测量工具状态
- */
- export function toggleHipNHAAngleMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleHipNHAAngleMeasurement] Toggling HipNHA measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleHipNHAAngleMeasurementTool(viewportId);
- }
- /**
- * 清除髋关节水平角测量标注
- */
- export function clearHipNHAAngleMeasurements(viewportId: string): boolean {
- console.log(
- `[clearHipNHAAngleMeasurements] Clearing HipNHA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearHipNHAAngleMeasurements(viewportId);
- }
- /**
- * 获取髋关节水平角测量结果
- */
- // eslint-disable-next-line
- export function getHipNHAAngleMeasurements(viewportId: string): any[] {
- console.log(
- `[getHipNHAAngleMeasurements] Getting HipNHA measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getHipNHAAngleMeasurements(viewportId);
- }
- /**
- * 检查髋关节水平角测量工具是否激活
- */
- export function isHipNHAAngleMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isHipNHAAngleMeasurementToolActive(viewportId);
- }
- // ==================== TPLO测量相关函数 ====================
- /**
- * 激活TPLO测量工具
- */
- export function activateTPLOMeasurement(viewportId: string): boolean {
- console.log(
- `[activateTPLOMeasurement] Activating TPLO measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.activateTPLOMeasurementTool(viewportId);
- }
- /**
- * 停用TPLO测量工具
- */
- export function deactivateTPLOMeasurement(viewportId: string): boolean {
- console.log(
- `[deactivateTPLOMeasurement] Deactivating TPLO measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.deactivateTPLOMeasurementTool(viewportId);
- }
- /**
- * 切换TPLO测量工具状态
- */
- export function toggleTPLOMeasurement(viewportId: string): boolean {
- console.log(
- `[toggleTPLOMeasurement] Toggling TPLO measurement for viewport: ${viewportId}`
- );
- return MeasurementToolManager.toggleTPLOMeasurementTool(viewportId);
- }
- /**
- * 清除TPLO测量标注
- */
- export function clearTPLOMeasurements(viewportId: string): boolean {
- console.log(
- `[clearTPLOMeasurements] Clearing TPLO measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.clearTPLOMeasurements(viewportId);
- }
- /**
- * 获取TPLO测量结果
- */
- // eslint-disable-next-line
- export function getTPLOMeasurements(viewportId: string): any[] {
- console.log(
- `[getTPLOMeasurements] Getting TPLO measurements for viewport: ${viewportId}`
- );
- return MeasurementToolManager.getTPLOMeasurements(viewportId);
- }
- /**
- * 检查TPLO测量工具是否激活
- */
- export function isTPLOMeasurementActive(viewportId: string): boolean {
- return MeasurementToolManager.isTPLOMeasurementToolActive(viewportId);
- }
- const StackViewer = ({
- imageIndex = 0,
- imageUrls = [],
- viewportId,
- renderingEngineId,
- selected
- }: {
- imageIndex?: number;
- imageUrls?: string[];
- viewportId: string;
- renderingEngineId: string;
- selected?: boolean;
- }) => {
- const elementRef = useRef<HTMLDivElement>(null);
- // const action = useSelector((state: RootState) => state.functionArea.action);
- // const dispatch = useDispatch();
- useEffect(() => {
- const setup = async () => {
- // // 初始化 Cornerstone
- // cornerstone.init();
- // cornerstoneTools.init();
- // const state = store.getState();
- // console.log(`当前系统模式:${state.systemMode.mode}`);
- // const token =
- // state.systemMode.mode === SystemMode.Emergency
- // ? state.product.guest
- // : state.userInfo.token;
- // console.log(`token stack.image.viewer: ${token}`);
- // cornerstoneDICOMImageLoader.init({
- // maxWebWorkers: navigator.hardwareConcurrency || 1,
- // errorInterceptor: (error) => {
- // if (error.status === 401) {
- // console.error('Authentication failed. Please refresh the token.');
- // }
- // console.error(`请求dcm文件出错:${error}`);
- // },
- // beforeSend: (xhr, imageId, defaultHeaders) => {
- // return {
- // ...defaultHeaders,
- // Authorization: `Bearer ${token}`,
- // Language: 'en',
- // Product: 'DROS',
- // Source: 'Electron',
- // };
- // },
- // });
- // const currentViewportId = viewportId;
- eventTarget.addEventListener(
- cornerstoneTools.Enums.Events.ANNOTATION_COMPLETED,
- (evt) => {
- const { annotation } = evt.detail;
- console.log('Annotation completed event:', annotation);
- if (annotation.metadata.toolName === 'LinearSplineROI') {
- console.log('SplineROITool annotation completed:', annotation);
- overlayRedRectangle(viewportId);
- //取消工具激活状态
- const toolGroup = ToolGroupManager.getToolGroup(
- 'STACK_TOOL_GROUP_ID'
- );
- if (!toolGroup) {
- console.log('toolGroup not found');
- }
- toolGroup?.setToolPassive('LinearSplineROI', {
- removeAllBindings: true,
- });
- }
- }
- );
- const viewportInput: cornerstone.Types.PublicViewportInput = {
- viewportId,
- element: elementRef.current!,
- type: cornerstone.Enums.ViewportType.STACK,
- };
- const renderingEngine = cornerstone.getRenderingEngine(renderingEngineId);
- if (!renderingEngine) {
- console.error(
- `[stack.image.viewer] No rendering engine with id ${renderingEngineId} found`
- );
- return;
- }
- // Enable the element for use with Cornerstone
- renderingEngine.enableElement(viewportInput);
- registerTools(viewportId, renderingEngine.id);
- // Get the stack viewport that was created
- const viewport = renderingEngine.getViewport(
- viewportId
- ) as cornerstone.Types.IStackViewport;
- // 给定一个dcm文件路径,加载并显示出来
- try {
- await viewport.setStack(imageUrls, imageIndex);
- } catch (error) {
- if (error instanceof Error) {
- console.error(
- '[stack.image.viewer] Error setting image stack:',
- error
- );
- } else {
- console.error('[stack.image.viewer] Unknown error:', error);
- }
- }
- viewport.render();
- };
- setup();
- }, [elementRef, imageIndex, viewportId, renderingEngineId]);
- return (
- <div
- ref={elementRef}
- onContextMenu={(e) => e.preventDefault()}
- style={{
- width: '100%', height: '100%', backgroundColor: '#000',
- border: selected
- ? '2px solid blue'
- : '1px solid gray',
- }}
- />
- );
- };
- export default StackViewer;
|