Browse Source

1、更新urm sell 绘制

guanxinyi 9 months ago
parent
commit
f121d4a276

+ 4 - 3
lib/process/calcuators/urm_calcuators/urm_ellipse_perfusion.dart

@@ -43,9 +43,10 @@ class URMEllipsePerfusionCal extends URMEllipseMeasureCal {
             if (outResult.perfusionImgBase64 != null) {
               feature.perfusionImg =
                   await loadImageFromBase64(outResult.perfusionImgBase64!);
-              feature.perfusionScaleDRect = urmApplication.viewToLocalRect(
-                outResult.perfusionScaleDRect!,
-              );
+              feature.leftTopPoint = urmApplication
+                  .viewToLocal(outResult.perfusionScaleDRect!.topLeft!);
+              feature.rightBottomPoint = urmApplication
+                  .viewToLocal(outResult.perfusionScaleDRect!.bottomRight!);
             }
           }
         }

+ 4 - 3
lib/process/calcuators/urm_calcuators/urm_rect_perfusion.dart

@@ -44,9 +44,10 @@ class URMRectPerfusionCal extends URMRectMeasureCal {
             if (outResult.perfusionImgBase64 != null) {
               feature.perfusionImg =
                   await loadImageFromBase64(outResult.perfusionImgBase64!);
-              feature.perfusionScaleDRect = urmApplication.viewToLocalRect(
-                outResult.perfusionScaleDRect!,
-              );
+              feature.leftTopPoint = urmApplication
+                  .viewToLocal(outResult.perfusionScaleDRect!.topLeft!);
+              feature.rightBottomPoint = urmApplication
+                  .viewToLocal(outResult.perfusionScaleDRect!.bottomRight!);
             }
           }
         }

+ 5 - 4
lib/process/calcuators/urm_calcuators/urm_shell_density_measure.dart

@@ -30,11 +30,12 @@ class URMShellDensityMeasureCal extends URMShellMeasureCal {
         return;
       }
       final feature = ref.feature!;
+      if (ref.meta.outputs.isNotEmpty) {
+        final first = ref.meta.outputs.first;
+        first.unit = VidUsUnit.percent;
 
-      final first = ref.meta.outputs.first;
-      first.unit = VidUsUnit.percent;
-
-      feature.updateFloatValue(first, outresult.resultData * 100, first.unit);
+        feature.updateFloatValue(first, outresult.resultData * 100, first.unit);
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;

+ 20 - 1
lib/process/calcuators/urm_calcuators/urm_shell_fractal_dim_measure.dart

@@ -1,9 +1,11 @@
 import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_measure.dart';
 import 'package:fis_measure/process/primitives/urm_measure/urm_shell_measure.dart';
 
 // import 'package:fis_measure/process/primitives/urm_straightline.dart';
 import 'package:fis_measure/process/workspace/urm/application.dart';
+import 'package:vid/us/vid_us_unit.dart';
 
 class URMShellFractalDimMeasureCal extends URMShellMeasureCal {
   URMShellFractalDimMeasureCal(URMShellMeasure ref) : super(ref);
@@ -16,11 +18,28 @@ class URMShellFractalDimMeasureCal extends URMShellMeasureCal {
     try {
       if (ref.feature == null) return;
       if (ref.application is! URMApplication) return;
+      final URMApplication urmApplication = ref.application as URMApplication;
 
-      // TODO 规划入参,坐标系转换,调用接口,处理返回结果
+      URMMeasureProcessResult? outresult =
+          await urmApplication.getURMMeasureResult(
+        urmMeasureType: URMMeasureType.URMFracetalDim,
+        rOIType: URMROIType.URMShell,
+        srcDPoints: param!.srcDPoints,
+      );
+      if (outresult == null) {
+        return;
+      }
+      final feature = ref.feature!;
+      if (ref.meta.outputs.isNotEmpty) {
+        final first = ref.meta.outputs.first;
+        first.unit = VidUsUnit.None;
+
+        feature.updateFloatValue(first, outresult.resultData, first.unit);
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;
     }
+    ref.application.updateRenderReady.emit(this, null);
   }
 }

+ 44 - 1
lib/process/calcuators/urm_calcuators/urm_shell_perfusion_measure.dart

@@ -1,9 +1,16 @@
+import 'dart:convert';
+import 'dart:typed_data';
+
+import 'dart:ui' as ui;
 import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_measure.dart';
 import 'package:fis_measure/process/primitives/urm_measure/urm_shell_measure.dart';
 
 // import 'package:fis_measure/process/primitives/urm_straightline.dart';
 import 'package:fis_measure/process/workspace/urm/application.dart';
+import 'package:vid/us/vid_us_unit.dart';
 
 class URMShellPerfusionMeasureCal extends URMShellMeasureCal {
   URMShellPerfusionMeasureCal(URMShellMeasure ref) : super(ref);
@@ -16,11 +23,47 @@ class URMShellPerfusionMeasureCal extends URMShellMeasureCal {
     try {
       if (ref.feature == null) return;
       if (ref.application is! URMApplication) return;
+      final URMApplication urmApplication = ref.application as URMApplication;
+
+      URMMeasureProcessResult? outResult =
+          await urmApplication.getURMMeasureResult(
+        urmMeasureType: URMMeasureType.URMPerfusion,
+        rOIType: URMROIType.URMShell,
+        srcDPoints: param!.srcDPoints,
+      );
+
+      if (outResult != null) {
+        final feature = ref.feature!;
 
-      // TODO 规划入参,坐标系转换,调用接口,处理返回结果
+        for (var output in ref.meta.outputs) {
+          if (output.name == MeasureTerms.URMPerfusionIndex) {
+            output.unit = VidUsUnit.None;
+            feature.updateFloatValue(output, outResult.resultData, output.unit);
+
+            if (feature is! ShellPerfusionImageFeature) return;
+            if (outResult.perfusionImgBase64 != null) {
+              feature.perfusionImg =
+                  await loadImageFromBase64(outResult.perfusionImgBase64!);
+              feature.perfusionScaleDRect = urmApplication.viewToLocalRect(
+                outResult.perfusionScaleDRect!,
+              );
+            }
+          }
+        }
+      } else {
+        throw Exception("URM Measure API error");
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;
     }
+    ref.application.updateRenderReady.emit(this, null);
+  }
+
+  Future<ui.Image> loadImageFromBase64(String base64String) async {
+    Uint8List bytes = base64Decode(base64String);
+    ui.Codec codec = await ui.instantiateImageCodec(bytes);
+    ui.FrameInfo frameInfo = await codec.getNextFrame();
+    return frameInfo.image;
   }
 }

+ 40 - 1
lib/process/calcuators/urm_calcuators/urm_shell_vel_measure.dart

@@ -1,9 +1,12 @@
 import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_measure.dart';
 import 'package:fis_measure/process/primitives/urm_measure/urm_shell_measure.dart';
 
 // import 'package:fis_measure/process/primitives/urm_straightline.dart';
 import 'package:fis_measure/process/workspace/urm/application.dart';
+import 'package:vid/us/vid_us_unit.dart';
 
 class URMShellVelMeasureCal extends URMShellMeasureCal {
   URMShellVelMeasureCal(URMShellMeasure ref) : super(ref);
@@ -16,11 +19,47 @@ class URMShellVelMeasureCal extends URMShellMeasureCal {
     try {
       if (ref.feature == null) return;
       if (ref.application is! URMApplication) return;
+      final URMApplication urmApplication = ref.application as URMApplication;
 
-      // TODO 规划入参,坐标系转换,调用接口,处理返回结果
+      URMMeasureProcessResult? outresult =
+          await urmApplication.getURMMeasureResult(
+        urmMeasureType: URMMeasureType.URMVelMeasure,
+        rOIType: URMROIType.URMShell,
+        srcDPoints: param!.srcDPoints,
+      );
+      if (outresult == null) {
+        return;
+      }
+      URMVelMeasureResult? result = outresult.velMeasureResult;
+
+      if (result != null) {
+        final feature = ref.feature!;
+
+        for (var output in ref.meta.outputs) {
+          if (output.name == MeasureTerms.URMVelMax) {
+            output.unit = VidUsUnit.mms;
+            feature.updateFloatValue(output, result.maxVel, output.unit);
+          } else if (output.name == MeasureTerms.URMVelMin) {
+            output.unit = VidUsUnit.mms;
+            feature.updateFloatValue(output, result.minVel, output.unit);
+          } else if (output.name == MeasureTerms.URMVelMean) {
+            output.unit = VidUsUnit.mms;
+            feature.updateFloatValue(output, result.meanVel, output.unit);
+          } else if (output.name == MeasureTerms.URMVelStd) {
+            output.unit = VidUsUnit.mms;
+            feature.updateFloatValue(output, result.varianceVel, output.unit);
+          } else if (output.name == MeasureTerms.Area) {
+            output.unit = VidUsUnit.cm2;
+            feature.updateFloatValue(output, result.roiArea, output.unit);
+          }
+        }
+      } else {
+        throw Exception("URM Measure API error");
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;
     }
+    ref.application.updateRenderReady.emit(this, null);
   }
 }

+ 5 - 4
lib/process/calcuators/urm_calcuators/urm_trace_density.dart

@@ -28,11 +28,12 @@ class URMTraceDensityCal extends URMTraceMeasureCal {
         return;
       }
       final feature = ref.feature!;
+      if (ref.meta.outputs.isNotEmpty) {
+        final first = ref.meta.outputs.first;
+        first.unit = VidUsUnit.percent;
 
-      final first = ref.meta.outputs.first;
-      first.unit = VidUsUnit.percent;
-
-      feature.updateFloatValue(first, outresult.resultData * 100, first.unit);
+        feature.updateFloatValue(first, outresult.resultData * 100, first.unit);
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;

+ 5 - 4
lib/process/calcuators/urm_calcuators/urm_trace_fractal_dim.dart

@@ -28,11 +28,12 @@ class URMTraceFractalDimCal extends URMTraceMeasureCal {
         return;
       }
       final feature = ref.feature!;
+      if (ref.meta.outputs.isNotEmpty) {
+        final first = ref.meta.outputs.first;
+        first.unit = VidUsUnit.None;
 
-      final first = ref.meta.outputs.first;
-      first.unit = VidUsUnit.None;
-
-      feature.updateFloatValue(first, outresult.resultData, first.unit);
+        feature.updateFloatValue(first, outresult.resultData, first.unit);
+      }
     } catch (e) {
       logger.e('URM Measure error: $e');
       return;

+ 4 - 5
lib/process/calcuators/urm_calcuators/urm_trace_hist.dart

@@ -28,11 +28,10 @@ class URMTraceHistCal extends URMTraceMeasureCal {
         return;
       }
       final feature = ref.feature!;
-
-      /// TODO 只转数据类型还不够,需要将 视图区域百分比坐标转为全图百分比坐标
-
-      final first = ref.meta.outputs.first;
-      first.unit = VidUsUnit.None;
+      if (ref.meta.outputs.isNotEmpty) {
+        final first = ref.meta.outputs.first;
+        first.unit = VidUsUnit.None;
+      }
 
       /// 超声机上面注释掉了
       // feature.updateFloatValue(first, outresult.resultData, first.unit);

+ 10 - 7
lib/process/primitives/urm_measure/urm_ellipse_measure.dart

@@ -161,7 +161,8 @@ class EllipsePerfusionImageFeature extends EllipseFeature {
 
   ui.Image? perfusionImg;
   IntRect? perfusionPiexlRect;
-  Rect? perfusionScaleDRect;
+  DPoint? leftTopPoint;
+  DPoint? rightBottomPoint;
   @override
   void paint(Canvas canvas, Size size) {
     if (perfusionImg != null) {
@@ -173,12 +174,14 @@ class EllipsePerfusionImageFeature extends EllipseFeature {
         perfusionImg!.width.toDouble(),
         perfusionImg!.height.toDouble(),
       );
-      Rect dst = Rect.fromLTWH(
-        perfusionScaleDRect!.left.toDouble() * size.width,
-        perfusionScaleDRect!.top.toDouble() * size.height,
-        perfusionScaleDRect!.width.toDouble() * size.width,
-        perfusionScaleDRect!.height.toDouble() * size.height,
-      );
+      if (leftTopPoint == null || rightBottomPoint == null) {
+        return;
+      }
+      DPoint leftTop = convert2ViewPoint(size, leftTopPoint!);
+      DPoint rightBottom = convert2ViewPoint(size, rightBottomPoint!);
+      convert2ViewPoint(size, rightBottomPoint!);
+      Rect dst = Rect.fromPoints(
+          Offset(leftTop.x, leftTop.y), Offset(rightBottom.x, rightBottom.y));
       canvas.drawImageRect(perfusionImg!, src, dst, paint);
     }
     super.paint(canvas, size);

+ 10 - 7
lib/process/primitives/urm_measure/urm_rect_measure.dart

@@ -210,7 +210,8 @@ class RectPerfusionImageFeature extends URMRectFeature {
 
   ui.Image? perfusionImg;
   IntRect? perfusionPiexlRect;
-  Rect? perfusionScaleDRect;
+  DPoint? leftTopPoint;
+  DPoint? rightBottomPoint;
   @override
   void paint(Canvas canvas, Size size) {
     if (perfusionImg != null) {
@@ -222,12 +223,14 @@ class RectPerfusionImageFeature extends URMRectFeature {
         perfusionImg!.width.toDouble(),
         perfusionImg!.height.toDouble(),
       );
-      Rect dst = Rect.fromLTWH(
-        perfusionScaleDRect!.left.toDouble() * size.width,
-        perfusionScaleDRect!.top.toDouble() * size.height,
-        perfusionScaleDRect!.width.toDouble() * size.width,
-        perfusionScaleDRect!.height.toDouble() * size.height,
-      );
+      if (leftTopPoint == null || rightBottomPoint == null) {
+        return;
+      }
+      DPoint leftTop = convert2ViewPoint(size, leftTopPoint!);
+      DPoint rightBottom = convert2ViewPoint(size, rightBottomPoint!);
+      convert2ViewPoint(size, rightBottomPoint!);
+      Rect dst = Rect.fromPoints(
+          Offset(leftTop.x, leftTop.y), Offset(rightBottom.x, rightBottom.y));
       canvas.drawImageRect(perfusionImg!, src, dst, paint);
     }
     super.paint(canvas, size);

+ 129 - 0
lib/process/primitives/urm_measure/urm_shell_measure.dart

@@ -1,5 +1,10 @@
+import 'dart:ui' as ui;
+
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:fis_measure/interfaces/enums/items.dart';
 import 'package:fis_measure/interfaces/process/items/item.dart';
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_den_measure.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_den_vel_measure.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_density_measure.dart';
@@ -7,10 +12,15 @@ import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_fractal_
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_hist_measure.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_perfusion_measure.dart';
 import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_vel_measure.dart';
+import 'package:fis_measure/process/primitives/area_abstract.dart';
 import 'package:fis_measure/process/primitives/trace.dart';
+import 'package:fis_measure/utils/prompt_box.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 
 class URMShellMeasure extends Trace {
   URMShellMeasure(super.meta, super.parent);
+  static bool needPerfusion = false;
 
   static URMShellMeasure createURMShellDenMeasure(ItemMeta meta,
       [IMeasureItem? parent]) {
@@ -50,6 +60,7 @@ class URMShellMeasure extends Trace {
 
   static URMShellMeasure createURMShellPerfusionMeasure(ItemMeta meta,
       [IMeasureItem? parent]) {
+    needPerfusion = true;
     URMShellMeasure measureShellPerfusion = URMShellMeasure(meta, parent);
     measureShellPerfusion.calculator = URMShellPerfusionMeasureCal(
       measureShellPerfusion,
@@ -74,4 +85,122 @@ class URMShellMeasure extends Trace {
     );
     return measureShellDenVel;
   }
+
+  @override
+  bool onExecuteMouse(PointInfo args) {
+    if (waitingResult) return false;
+    if (state == ItemStates.finished) {
+      if (args.pointType == PointInfoType.mouseDown) {
+        state = ItemStates.waiting;
+      }
+    }
+
+    if (state == ItemStates.waiting) {
+      if (args.pointType == PointInfoType.mouseDown) {
+        handleMouseDownWhileWaiting(args);
+      }
+    } else if (state == ItemStates.running) {
+      if (args.pointType == PointInfoType.mouseUp) return false;
+
+      feature?.adopt(args);
+      if (args.pointType == PointInfoType.mouseDown) {
+        handleFinish();
+      } else {
+        checkAutoSnap(args);
+      }
+    }
+    return true;
+  }
+
+  @override
+  void handleMouseDownWhileWaiting(PointInfo args) {
+    if (needPerfusion) {
+      feature = ShellPerfusionImageFeature(this);
+    } else {
+      super.handleMouseDownWhileWaiting(args);
+    }
+    state = ItemStates.running;
+  }
+
+  bool waitingResult = false;
+
+  void handleFinish() async {
+    feature!.isActive = false;
+    PromptBox.loading("计算中...");
+    waitingResult = true;
+    await doCalculateAsync();
+    doFeatureFinish();
+    PromptBox.dismiss();
+    waitingResult = false;
+  }
+
+  /// 自动结束检测
+  @override
+  bool checkAutoSnap(PointInfo current, [bool autoFinishFeature = true]) {
+    if (feature == null || feature!.innerPoints.length < 3) {
+      isSmartMove = false;
+      return _syncState(false);
+    }
+
+    // final viewport = feature!.hostVisualArea!.viewport!;
+
+    if (isAutoSnap == false) return false;
+    final pixelSize = application.displaySize;
+
+    final p1 = feature!.innerPoints.first.scale2Size(pixelSize);
+    final p2 = current.scale2Size(pixelSize);
+    final length = (p1 - p2).length;
+    if (length > snapThreshold * 2.0 && !isSmartMove) {
+      isSmartMove = true;
+    }
+    if (length < snapThreshold && isSmartMove) {
+      feature!.innerPoints.last = feature!.innerPoints.first.clone();
+
+      /// 此处的最后一个点,方便计算,但是绘制时要剔除
+      // feature!.innerPoints.removeLast();
+
+      HapticFeedback.heavyImpact();
+      if (autoFinishFeature) {
+        handleFinish();
+      }
+      isSmartMove = false;
+      return _syncState(true);
+    } else {
+      return _syncState(false);
+    }
+  }
+
+  bool _syncState(bool isSnap) {
+    snapState = isSnap;
+    return snapState;
+  }
+}
+
+class ShellPerfusionImageFeature extends TraceFeature {
+  ShellPerfusionImageFeature(AreaItemAbstract refItem) : super(refItem);
+
+  ui.Image? perfusionImg;
+  IntRect? perfusionPiexlRect;
+  Rect? perfusionScaleDRect;
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (perfusionImg != null) {
+      Paint paint = Paint();
+
+      Rect src = Rect.fromLTWH(
+        0,
+        0,
+        perfusionImg!.width.toDouble(),
+        perfusionImg!.height.toDouble(),
+      );
+      Rect dst = Rect.fromLTWH(
+        perfusionScaleDRect!.left.toDouble() * size.width,
+        perfusionScaleDRect!.top.toDouble() * size.height,
+        perfusionScaleDRect!.width.toDouble() * size.width,
+        perfusionScaleDRect!.height.toDouble() * size.height,
+      );
+      canvas.drawImageRect(perfusionImg!, src, dst, paint);
+    }
+    super.paint(canvas, size);
+  }
 }