Parcourir la source

添加动物专用测量工具--VHS心锥比

sw il y a 2 jours
Parent
commit
eb7263e60a

+ 35 - 0
src/pages/view/components/ViewerContainer.tsx

@@ -415,6 +415,7 @@ const ViewerContainer: React.FC<ViewerContainerProps> = ({ imageUrls }) => {
             MeasurementToolManager.clearDARAMeasurementsForViewports(selectedViewportIds);
             MeasurementToolManager.clearHipDIMeasurementsForViewports(selectedViewportIds);
             MeasurementToolManager.clearHipNHAAngleMeasurementsForViewports(selectedViewportIds);
+            MeasurementToolManager.clearVHSMeasurementsForViewports(selectedViewportIds);
           }
           console.log('Clearing All Measurements from MeasurementPanel');
           break;
@@ -591,6 +592,40 @@ const ViewerContainer: React.FC<ViewerContainerProps> = ({ imageUrls }) => {
           console.log('Activating HipNHA Measurement from MeasurementPanel');
           break;
 
+        case '心锥比':
+          console.log(`开始心锥比测量`);
+          if (selectedViewportIds.length > 0) {
+            selectedViewportIds.forEach((viewportId) => {
+              const success = MeasurementToolManager.activateVHSMeasurementTool(viewportId);
+              if (success) {
+                console.log(`激活心锥比测量工具成功`);
+                dispatch(
+                  setToolActive({
+                    toolName: 'VHSMeasurementTool',
+                    viewportId: viewportId,
+                  })
+                );
+              }
+            });
+          } else {
+            // 如果没有选中的 viewport,为所有可见的 viewport 激活
+            const visibleViewportCount = getVisibleViewportCount();
+            for (let i = 0; i < visibleViewportCount; i++) {
+              const viewportId = `viewport-${i}`;
+              const success = MeasurementToolManager.activateVHSMeasurementTool(viewportId);
+              if (success) {
+                dispatch(
+                  setToolActive({
+                    toolName: 'VHSMeasurementTool',
+                    viewportId: viewportId,
+                  })
+                );
+              }
+            }
+          }
+          console.log('Activating VHS Measurement from MeasurementPanel');
+          break;
+
         case '测量校正':
           console.log('Measurement Calibration - 功能待实现');
           break;

+ 3 - 0
src/pages/view/components/viewers/stack.image.viewer.tsx

@@ -10,6 +10,7 @@ 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 { boolean } from 'zod';
 
 const {
@@ -125,6 +126,7 @@ function registerTools(viewportId, renderingEngineId) {
   toolGroup.addTool(DARAMeasurementTool.toolName); // 添加髋臼水平角测量工具
   toolGroup.addTool(HipDIMeasurementTool.toolName); // 添加髋关节牵引指数测量工具
   toolGroup.addTool(HipNHAAngleMeasurementTool.toolName); // 添加髋关节水平角测量工具
+  toolGroup.addTool(VHSMeasurementTool.toolName); // 添加心锥比测量工具
 
   // 设置默认工具状态
   setupDefaultToolStates(toolGroup);
@@ -177,6 +179,7 @@ function setupDefaultToolStates(toolGroup: cornerstoneTools.Types.IToolGroup) {
   toolGroup.setToolPassive(DARAMeasurementTool.toolName);
   toolGroup.setToolPassive(HipDIMeasurementTool.toolName);
   toolGroup.setToolPassive(HipNHAAngleMeasurementTool.toolName);
+  toolGroup.setToolPassive(VHSMeasurementTool.toolName);
 }
 export function addLMark(currentViewportId: string): void {
   // Implement the logic to add an L mark

+ 1 - 0
src/states/view/measurementPanelSlice.ts

@@ -11,6 +11,7 @@ export type MeasurementAction =
   | '髋臼水平角'
   | '髋关节水平角'
   | '髋关节牵引指数'
+  | '心锥比'
   | null;
 
 // 测量结果类型

+ 2 - 0
src/utils/cornerstoneToolsSetup.ts

@@ -3,6 +3,7 @@ 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';
 
 const {
   MagnifyTool,
@@ -46,6 +47,7 @@ export function registerGlobalTools(): void {
     cornerstoneTools.addTool(DARAMeasurementTool); // 添加髋臼水平角测量工具
     cornerstoneTools.addTool(HipDIMeasurementTool); // 添加髋关节牵引指数测量工具
     cornerstoneTools.addTool(HipNHAAngleMeasurementTool); // 添加髋关节水平角测量工具
+    cornerstoneTools.addTool(VHSMeasurementTool); // 添加心锥比测量工具
 
     toolsRegistered = true;
     console.log('[cornerstoneToolsSetup] All tools registered successfully');

+ 270 - 0
src/utils/measurementToolManager.ts

@@ -4,6 +4,7 @@ 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';
 
 const {
   ToolGroupManager,
@@ -1475,4 +1476,273 @@ export class MeasurementToolManager {
       this.clearHipNHAAngleMeasurements(viewportId)
     );
   }
+
+  // ==================== 心锥比测量工具 ====================
+
+  /**
+   * 激活心锥比测量工具
+   */
+  static activateVHSMeasurementTool(viewportId: string): boolean {
+    const toolGroup = this.getToolGroup(viewportId);
+    if (!toolGroup) return false;
+
+    try {
+      // 停用其他可能冲突的工具
+      toolGroup.setToolPassive(WindowLevelTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(MagnifyTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(LengthTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(AngleTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(TibialPlateauAngleTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(DARAMeasurementTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(HipDIMeasurementTool.toolName, {
+        removeAllBindings: true,
+      });
+      toolGroup.setToolPassive(HipNHAAngleMeasurementTool.toolName, {
+        removeAllBindings: true,
+      });
+
+      // 激活心锥比测量工具
+      toolGroup.setToolActive(VHSMeasurementTool.toolName, {
+        bindings: [{ mouseButton: MouseBindings.Primary }],
+      });
+
+      // 获取工具实例并激活修改模式
+      const toolInstance = toolGroup.getToolInstance(
+        VHSMeasurementTool.toolName
+      ) as VHSMeasurementTool;
+
+      const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
+      if (toolInstance && viewport.element) {
+        toolInstance._activateModify(viewport.element);
+      }
+
+      // 自动创建一个预设的注解
+      try {
+        if (viewport && viewport.element) {
+          // 创建预设注解
+          const defaultAnnotation = VHSMeasurementTool.createDefaultAnnotation(
+            viewport.element as HTMLDivElement,
+            viewport as cornerstone.Types.IStackViewport
+          );
+
+          // 添加注解到状态管理
+          cornerstoneTools.annotation.state.addAnnotation(
+            defaultAnnotation,
+            viewport.element
+          );
+
+          // 获取工具实例并更新缓存统计数据
+          const enabledElement = cornerstone.getEnabledElement(viewport.element);
+          if (enabledElement) {
+            const toolInstance = toolGroup.getToolInstance(
+              VHSMeasurementTool.toolName
+            ) as VHSMeasurementTool;
+
+            if (toolInstance && '_updateCachedStats' in toolInstance) {
+              (toolInstance as any)._updateCachedStats(defaultAnnotation, enabledElement);
+            }
+          }
+
+          // 触发渲染更新
+          viewport.render();
+
+          console.log('[MeasurementToolManager] Default VHS annotation created successfully');
+        }
+      } catch (error) {
+        console.error('[MeasurementToolManager] Failed to create default VHS annotation:', error);
+        // 注解创建失败不影响工具激活
+      }
+
+      console.log(
+        `[MeasurementToolManager] VHS tool activated for viewport: ${viewportId}`
+      );
+      return true;
+    } catch (error) {
+      console.error(
+        `[MeasurementToolManager] Error activating VHS tool:`,
+        error
+      );
+      return false;
+    }
+  }
+
+  /**
+   * 停用心锥比测量工具
+   */
+  static deactivateVHSMeasurementTool(viewportId: string): boolean {
+    const toolGroup = this.getToolGroup(viewportId);
+    if (!toolGroup) return false;
+
+    try {
+      toolGroup.setToolPassive(VHSMeasurementTool.toolName, {
+        removeAllBindings: true,
+      });
+      console.log(
+        `[MeasurementToolManager] VHS tool deactivated for viewport: ${viewportId}`
+      );
+      return true;
+    } catch (error) {
+      console.error(
+        `[MeasurementToolManager] Error deactivating VHS tool:`,
+        error
+      );
+      return false;
+    }
+  }
+
+  /**
+   * 检查心锥比测量工具是否处于激活状态
+   */
+  static isVHSMeasurementToolActive(viewportId: string): boolean {
+    const toolGroup = this.getToolGroup(viewportId);
+    if (!toolGroup) return false;
+
+    try {
+      const activeTool = toolGroup.getActivePrimaryMouseButtonTool();
+      return activeTool === VHSMeasurementTool.toolName;
+    } catch (error) {
+      console.error(
+        `[MeasurementToolManager] Error checking VHS tool state:`,
+        error
+      );
+      return false;
+    }
+  }
+
+  /**
+   * 切换心锥比测量工具状态
+   */
+  static toggleVHSMeasurementTool(viewportId: string): boolean {
+    const isActive = this.isVHSMeasurementToolActive(viewportId);
+
+    if (isActive) {
+      return this.deactivateVHSMeasurementTool(viewportId);
+    } else {
+      return this.activateVHSMeasurementTool(viewportId);
+    }
+  }
+
+  /**
+   * 清除指定 viewport 的所有心锥比测量标注
+   */
+  static clearVHSMeasurements(viewportId: string): boolean {
+    try {
+      const viewport =
+        cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
+      if (!viewport) {
+        console.warn(
+          `[MeasurementToolManager] Viewport not found: ${viewportId}`
+        );
+        return false;
+      }
+
+      const annotations = cornerstoneTools.annotation.state.getAnnotations(
+        VHSMeasurementTool.toolName,
+        viewport.element
+      );
+
+      let removedCount = 0;
+      annotations.forEach((annotation) => {
+        if (annotation.annotationUID) {
+          cornerstoneTools.annotation.state.removeAnnotation(
+            annotation.annotationUID
+          );
+          removedCount++;
+        }
+      });
+
+      viewport.render();
+      console.log(
+        `[MeasurementToolManager] Cleared ${removedCount} VHS measurements for viewport: ${viewportId}`
+      );
+      return true;
+    } catch (error) {
+      console.error(
+        `[MeasurementToolManager] Error clearing VHS measurements:`,
+        error
+      );
+      return false;
+    }
+  }
+
+  /**
+   * 获取指定 viewport 的所有心锥比测量结果
+   */
+  // eslint-disable-next-line
+  static getVHSMeasurements(viewportId: string): any[] {
+    try {
+      const viewport =
+        cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
+      if (!viewport) {
+        console.warn(
+          `[MeasurementToolManager] Viewport not found: ${viewportId}`
+        );
+        return [];
+      }
+
+      const annotations = cornerstoneTools.annotation.state.getAnnotations(
+        VHSMeasurementTool.toolName,
+        viewport.element
+      );
+
+      return annotations.map((annotation) => ({
+        annotationUID: annotation.annotationUID,
+        vhs: annotation.data?.cachedStats?.vhs || 0,
+        longAxisCount: annotation.data?.cachedStats?.longAxisCount || 0,
+        shortAxisCount: annotation.data?.cachedStats?.shortAxisCount || 0,
+        ratio: annotation.data?.cachedStats?.ratio || 0,
+        unit: 'ratio',
+        points: annotation.data?.handles?.points || [],
+      }));
+    } catch (error) {
+      console.error(
+        `[MeasurementToolManager] Error getting VHS measurements:`,
+        error
+      );
+      return [];
+    }
+  }
+
+  /**
+   * 为多个 viewport 批量激活心锥比测量工具
+   */
+  static activateVHSMeasurementToolForViewports(
+    viewportIds: string[]
+  ): boolean[] {
+    return viewportIds.map((viewportId) =>
+      this.activateVHSMeasurementTool(viewportId)
+    );
+  }
+
+  /**
+   * 为多个 viewport 批量停用心锥比测量工具
+   */
+  static deactivateVHSMeasurementToolForViewports(
+    viewportIds: string[]
+  ): boolean[] {
+    return viewportIds.map((viewportId) =>
+      this.deactivateVHSMeasurementTool(viewportId)
+    );
+  }
+
+  /**
+   * 为多个 viewport 批量清除心锥比测量
+   */
+  static clearVHSMeasurementsForViewports(viewportIds: string[]): boolean[] {
+    return viewportIds.map((viewportId) =>
+      this.clearVHSMeasurements(viewportId)
+    );
+  }
 }