|
@@ -6,6 +6,10 @@ import HipDIMeasurementTool from '@/components/measures/HipDIMeasurementTool';
|
|
import HipNHAAngleMeasurementTool from '@/components/measures/HipNHAAngleMeasurementTool';
|
|
import HipNHAAngleMeasurementTool from '@/components/measures/HipNHAAngleMeasurementTool';
|
|
import VHSMeasurementTool from '@/components/measures/VHSMeasurementTool';
|
|
import VHSMeasurementTool from '@/components/measures/VHSMeasurementTool';
|
|
import TPLOMeasurementTool from '@/components/measures/TPLOMeasurementTool';
|
|
import TPLOMeasurementTool from '@/components/measures/TPLOMeasurementTool';
|
|
|
|
+import TTAMeasurementTool from '@/components/measures/TTAMeasurementTool';
|
|
|
|
+import CBLOMeasurementTool from '@/components/measures/CBLOMeasurementTool';
|
|
|
|
+import HipCoverageMeasurementTool from '@/components/measures/HipCoverageMeasurementTool';
|
|
|
|
+import HipDorsalCoverageTool from '@/components/measures/HipDorsalCoverageTool';
|
|
|
|
|
|
const {
|
|
const {
|
|
ToolGroupManager,
|
|
ToolGroupManager,
|
|
@@ -2017,4 +2021,600 @@ export class MeasurementToolManager {
|
|
this.clearTPLOMeasurements(viewportId)
|
|
this.clearTPLOMeasurements(viewportId)
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // ==================== TTA测量工具 ====================
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 激活TTA测量工具
|
|
|
|
+ */
|
|
|
|
+ static activateTTAMeasurementTool(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.setToolPassive(VHSMeasurementTool.toolName, {
|
|
|
|
+ removeAllBindings: true,
|
|
|
|
+ });
|
|
|
|
+ toolGroup.setToolPassive(TPLOMeasurementTool.toolName, {
|
|
|
|
+ removeAllBindings: true,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 激活TTA测量工具
|
|
|
|
+ toolGroup.setToolActive(TTAMeasurementTool.toolName, {
|
|
|
|
+ bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 获取工具实例并激活修改模式
|
|
|
|
+ const toolInstance = toolGroup.getToolInstance(
|
|
|
|
+ TTAMeasurementTool.toolName
|
|
|
|
+ ) as TTAMeasurementTool;
|
|
|
|
+
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (toolInstance && viewport.element) {
|
|
|
|
+ toolInstance._activateModify(viewport.element);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 自动创建一个预设的注解
|
|
|
|
+ try {
|
|
|
|
+ if (viewport && viewport.element) {
|
|
|
|
+ // 创建预设注解
|
|
|
|
+ const defaultAnnotation = TTAMeasurementTool.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(
|
|
|
|
+ TTAMeasurementTool.toolName
|
|
|
|
+ ) as TTAMeasurementTool;
|
|
|
|
+
|
|
|
|
+ if (toolInstance && '_updateCachedStats' in toolInstance) {
|
|
|
|
+ (toolInstance as any)._updateCachedStats(defaultAnnotation, enabledElement);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 触发渲染更新
|
|
|
|
+ viewport.render();
|
|
|
|
+
|
|
|
|
+ console.log('[MeasurementToolManager] Default TTA annotation created successfully');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('[MeasurementToolManager] Failed to create default TTA annotation:', error);
|
|
|
|
+ // 注解创建失败不影响工具激活
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log(
|
|
|
|
+ `[MeasurementToolManager] TTA tool activated for viewport: ${viewportId}`
|
|
|
|
+ );
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(
|
|
|
|
+ `[MeasurementToolManager] Error activating TTA tool:`,
|
|
|
|
+ error
|
|
|
|
+ );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 停用TTA测量工具
|
|
|
|
+ */
|
|
|
|
+ static deactivateTTAMeasurementTool(viewportId: string): boolean {
|
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
|
+ if (!toolGroup) return false;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ toolGroup.setToolPassive(TTAMeasurementTool.toolName, {
|
|
|
|
+ removeAllBindings: true,
|
|
|
|
+ });
|
|
|
|
+ console.log(
|
|
|
|
+ `[MeasurementToolManager] TTA tool deactivated for viewport: ${viewportId}`
|
|
|
|
+ );
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(
|
|
|
|
+ `[MeasurementToolManager] Error deactivating TTA tool:`,
|
|
|
|
+ error
|
|
|
|
+ );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 检查TTA测量工具是否处于激活状态
|
|
|
|
+ */
|
|
|
|
+ static isTTAMeasurementToolActive(viewportId: string): boolean {
|
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
|
+ if (!toolGroup) return false;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ const activeTool = toolGroup.getActivePrimaryMouseButtonTool();
|
|
|
|
+ return activeTool === TTAMeasurementTool.toolName;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(
|
|
|
|
+ `[MeasurementToolManager] Error checking TTA tool state:`,
|
|
|
|
+ error
|
|
|
|
+ );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 切换TTA测量工具状态
|
|
|
|
+ */
|
|
|
|
+ static toggleTTAMeasurementTool(viewportId: string): boolean {
|
|
|
|
+ const isActive = this.isTTAMeasurementToolActive(viewportId);
|
|
|
|
+
|
|
|
|
+ if (isActive) {
|
|
|
|
+ return this.deactivateTTAMeasurementTool(viewportId);
|
|
|
|
+ } else {
|
|
|
|
+ return this.activateTTAMeasurementTool(viewportId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 清除指定 viewport 的所有TTA测量标注
|
|
|
|
+ */
|
|
|
|
+ static clearTTAMeasurements(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(
|
|
|
|
+ TTAMeasurementTool.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} TTA measurements for viewport: ${viewportId}`
|
|
|
|
+ );
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(
|
|
|
|
+ `[MeasurementToolManager] Error clearing TTA measurements:`,
|
|
|
|
+ error
|
|
|
|
+ );
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取指定 viewport 的所有TTA测量结果
|
|
|
|
+ */
|
|
|
|
+ // eslint-disable-next-line
|
|
|
|
+ static getTTAMeasurements(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(
|
|
|
|
+ TTAMeasurementTool.toolName,
|
|
|
|
+ viewport.element
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ return annotations.map((annotation) => ({
|
|
|
|
+ annotationUID: annotation.annotationUID,
|
|
|
|
+ ttaDistance: annotation.data?.cachedStats?.ttaDistance || 0,
|
|
|
|
+ unit: 'mm',
|
|
|
|
+ points: annotation.data?.handles?.points || [],
|
|
|
|
+ }));
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(
|
|
|
|
+ `[MeasurementToolManager] Error getting TTA measurements:`,
|
|
|
|
+ error
|
|
|
|
+ );
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 为多个 viewport 批量激活TTA测量工具
|
|
|
|
+ */
|
|
|
|
+ static activateTTAMeasurementToolForViewports(
|
|
|
|
+ viewportIds: string[]
|
|
|
|
+ ): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) =>
|
|
|
|
+ this.activateTTAMeasurementTool(viewportId)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 为多个 viewport 批量停用TTA测量工具
|
|
|
|
+ */
|
|
|
|
+ static deactivateTTAMeasurementToolForViewports(
|
|
|
|
+ viewportIds: string[]
|
|
|
|
+ ): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) =>
|
|
|
|
+ this.deactivateTTAMeasurementTool(viewportId)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 为多个 viewport 批量清除TTA测量
|
|
|
|
+ */
|
|
|
|
+ static clearTTAMeasurementsForViewports(viewportIds: string[]): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) =>
|
|
|
|
+ this.clearTTAMeasurements(viewportId)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ==================== CBLO(水平截骨术)测量工具 ====================
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 激活CBLO测量工具
|
|
|
|
+ */
|
|
|
|
+ static activateCBLOMeasurementTool(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.setToolPassive(VHSMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TPLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TTAMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+
|
|
|
|
+ toolGroup.setToolActive(CBLOMeasurementTool.toolName, {
|
|
|
|
+ bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const toolInstance = toolGroup.getToolInstance(CBLOMeasurementTool.toolName) as CBLOMeasurementTool;
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (toolInstance && viewport.element) {
|
|
|
|
+ toolInstance._activateModify(viewport.element);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ if (viewport && viewport.element) {
|
|
|
|
+ const defaultAnnotation = CBLOMeasurementTool.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(CBLOMeasurementTool.toolName) as CBLOMeasurementTool;
|
|
|
|
+ if (toolInstance && '_updateCachedStats' in toolInstance) {
|
|
|
|
+ (toolInstance as any)._updateCachedStats(defaultAnnotation, enabledElement);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ viewport.render();
|
|
|
|
+ console.log('[MeasurementToolManager] Default CBLO annotation created successfully');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('[MeasurementToolManager] Failed to create default CBLO annotation:', error);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log(`[MeasurementToolManager] CBLO tool activated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error activating CBLO tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static deactivateCBLOMeasurementTool(viewportId: string): boolean {
|
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
|
+ if (!toolGroup) return false;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ toolGroup.setToolPassive(CBLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ console.log(`[MeasurementToolManager] CBLO tool deactivated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error deactivating CBLO tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearCBLOMeasurements(viewportId: string): boolean {
|
|
|
|
+ try {
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (!viewport) return false;
|
|
|
|
+
|
|
|
|
+ const annotations = cornerstoneTools.annotation.state.getAnnotations(
|
|
|
|
+ CBLOMeasurementTool.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} CBLO measurements for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error clearing CBLO measurements:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearCBLOMeasurementsForViewports(viewportIds: string[]): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) => this.clearCBLOMeasurements(viewportId));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ==================== HipCoverage(股骨头覆盖率)测量工具 ====================
|
|
|
|
+
|
|
|
|
+ static activateHipCoverageMeasurementTool(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.setToolPassive(VHSMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TPLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TTAMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(CBLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+
|
|
|
|
+ toolGroup.setToolActive(HipCoverageMeasurementTool.toolName, {
|
|
|
|
+ bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const toolInstance = toolGroup.getToolInstance(HipCoverageMeasurementTool.toolName) as HipCoverageMeasurementTool;
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (toolInstance && viewport.element) {
|
|
|
|
+ toolInstance._activateModify(viewport.element);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ if (viewport && viewport.element) {
|
|
|
|
+ const defaultAnnotation = HipCoverageMeasurementTool.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(HipCoverageMeasurementTool.toolName) as HipCoverageMeasurementTool;
|
|
|
|
+ if (toolInstance && '_updateCachedStats' in toolInstance) {
|
|
|
|
+ (toolInstance as any)._updateCachedStats(defaultAnnotation, enabledElement);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ viewport.render();
|
|
|
|
+ console.log('[MeasurementToolManager] Default HipCoverage annotation created successfully');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('[MeasurementToolManager] Failed to create default HipCoverage annotation:', error);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log(`[MeasurementToolManager] HipCoverage tool activated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error activating HipCoverage tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static deactivateHipCoverageMeasurementTool(viewportId: string): boolean {
|
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
|
+ if (!toolGroup) return false;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ toolGroup.setToolPassive(HipCoverageMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ console.log(`[MeasurementToolManager] HipCoverage tool deactivated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error deactivating HipCoverage tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearHipCoverageMeasurements(viewportId: string): boolean {
|
|
|
|
+ try {
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (!viewport) return false;
|
|
|
|
+
|
|
|
|
+ const annotations = cornerstoneTools.annotation.state.getAnnotations(
|
|
|
|
+ HipCoverageMeasurementTool.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} HipCoverage measurements for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error clearing HipCoverage measurements:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearHipCoverageMeasurementsForViewports(viewportIds: string[]): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) => this.clearHipCoverageMeasurements(viewportId));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ==================== HipDorsalCoverage(髋臼背覆盖)测量工具 ====================
|
|
|
|
+
|
|
|
|
+ static activateHipDorsalCoverageTool(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.setToolPassive(VHSMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TPLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(TTAMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(CBLOMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+ toolGroup.setToolPassive(HipCoverageMeasurementTool.toolName, { removeAllBindings: true });
|
|
|
|
+
|
|
|
|
+ toolGroup.setToolActive(HipDorsalCoverageTool.toolName, {
|
|
|
|
+ bindings: [{ mouseButton: MouseBindings.Primary }],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const toolInstance = toolGroup.getToolInstance(HipDorsalCoverageTool.toolName) as HipDorsalCoverageTool;
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (toolInstance && viewport.element) {
|
|
|
|
+ toolInstance._activateModify(viewport.element);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ if (viewport && viewport.element) {
|
|
|
|
+ const defaultAnnotation = HipDorsalCoverageTool.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(HipDorsalCoverageTool.toolName) as HipDorsalCoverageTool;
|
|
|
|
+ if (toolInstance && '_updateCachedStats' in toolInstance) {
|
|
|
|
+ (toolInstance as any)._updateCachedStats(defaultAnnotation, enabledElement);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ viewport.render();
|
|
|
|
+ console.log('[MeasurementToolManager] Default HipDorsalCoverage annotation created successfully');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('[MeasurementToolManager] Failed to create default HipDorsalCoverage annotation:', error);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.log(`[MeasurementToolManager] HipDorsalCoverage tool activated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error activating HipDorsalCoverage tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static deactivateHipDorsalCoverageTool(viewportId: string): boolean {
|
|
|
|
+ const toolGroup = this.getToolGroup(viewportId);
|
|
|
|
+ if (!toolGroup) return false;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ toolGroup.setToolPassive(HipDorsalCoverageTool.toolName, { removeAllBindings: true });
|
|
|
|
+ console.log(`[MeasurementToolManager] HipDorsalCoverage tool deactivated for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error deactivating HipDorsalCoverage tool:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearHipDorsalCoverageMeasurements(viewportId: string): boolean {
|
|
|
|
+ try {
|
|
|
|
+ const viewport = cornerstone.getEnabledElementByViewportId(viewportId)?.viewport;
|
|
|
|
+ if (!viewport) return false;
|
|
|
|
+
|
|
|
|
+ const annotations = cornerstoneTools.annotation.state.getAnnotations(
|
|
|
|
+ HipDorsalCoverageTool.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} HipDorsalCoverage measurements for viewport: ${viewportId}`);
|
|
|
|
+ return true;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`[MeasurementToolManager] Error clearing HipDorsalCoverage measurements:`, error);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static clearHipDorsalCoverageMeasurementsForViewports(viewportIds: string[]): boolean[] {
|
|
|
|
+ return viewportIds.map((viewportId) => this.clearHipDorsalCoverageMeasurements(viewportId));
|
|
|
|
+ }
|
|
}
|
|
}
|