فهرست منبع

fix(measure): 完成 HR 测量项 #0008940

gavin.chen 2 سال پیش
والد
کامیت
d79b1905dc

+ 3 - 3
lib/measure_page_test.dart

@@ -99,9 +99,9 @@ class _MeasureTestPageState extends State<MeasureTestPage> {
       // "http://cdn-bj.fis.plus/9F066341FA874E21B48CDE247C13D495.vid"; //B TVI TD
       // "http://cdn-bj.fis.plus/974BABA5113640639FD749E06DD7DA5B.vid"; //B CF CW
       // "http://cdn-bj.fis.plus/0B344F48BA574ECD82B7FEDB8848421A.vid"; //单幅TM
-      // "http://cdn-bj.fis.plus/3379F38302884C2991D90FBDFB0DEA7E.dat"; //单幅TM(2)
-      // "http://cdn-bj.fis.plus/6A99AD2530864616B64355A8EA9AE3EC.vid";
-      "http://cdn-bj.fis.plus/F26C6E5D57A7472A97E9EB543DF0D16C.vid"; // 单幅Convex
+      "http://cdn-bj.fis.plus/3379F38302884C2991D90FBDFB0DEA7E.dat"; //单幅TM(2)
+  // "http://cdn-bj.fis.plus/6A99AD2530864616B64355A8EA9AE3EC.vid";
+  // "http://cdn-bj.fis.plus/F26C6E5D57A7472A97E9EB543DF0D16C.vid"; // 单幅Convex
   // "http://cdn-bj.fis.plus/6B6E069659D14E7299EB9F6EFCDE9C8C.vid"; //双幅单TissueConvex
   // "http://cdn-bj.fis.plus/062643B82365437DB95F3811580AF3ED.vid"; //四幅单模式
   // "http://cdn-bj.fis.plus/EA90D146049D416E8E466B7446E00001.vid"; //四幅Doppler

+ 8 - 9
lib/process/calcuators/heart_rate.dart

@@ -1,20 +1,17 @@
 import 'package:fis_measure/interfaces/process/items/terms.dart';
-
-import '../primitives/straightline.dart';
+import 'package:fis_measure/process/primitives/single_straightline.dart';
 import 'calculator.dart';
 
-class HeartRateCal extends Calculator<StraightLine, double> {
-  HeartRateCal(StraightLine ref) : super(ref);
+class HeartRateCal extends Calculator<SingleStraightLine, double> {
+  HeartRateCal(SingleStraightLine ref) : super(ref);
 
   @override
   void calculate() {
     if (ref.feature == null) return;
+    if (ref.feature!.innerPoints.length < 2) return;
 
     final feature = ref.feature! as StraightLineHeartRateFeature;
-    print("心跳循环数:${feature.heartCycle}");
-    //修改心跳周期
-    //feature.setHeartRate(2);
-
+    if (feature.startPoint == feature.endPoint) return;
     final heartCycle = feature.heartCycle;
     final viewport = feature.hostVisualArea!.viewport!;
     final p1 = feature.startPoint;
@@ -23,7 +20,9 @@ class HeartRateCal extends Calculator<StraightLine, double> {
     final pp2 = viewport.convert(p2);
 
     final time = (pp2.x - pp1.x).abs();
-    final hr = (heartCycle / time) * 60;
+    double hr = (heartCycle / time) * 60;
+    if (time == 0) hr = 0;
+
     for (var output in ref.meta.outputs) {
       if (output.name == MeasureTerms.HeartRate) {
         feature.updateFloatValue(output, hr, output.unit);

+ 2 - 1
lib/process/items/factory.dart

@@ -17,6 +17,7 @@ import 'package:fis_measure/process/primitives/multi_method/multiple_trace.dart'
 import 'package:fis_measure/process/primitives/polyline.dart';
 import 'package:fis_measure/process/primitives/polyline_angle.dart';
 import 'package:fis_measure/process/primitives/ray.dart';
+import 'package:fis_measure/process/primitives/single_straightline.dart';
 import 'package:fis_measure/process/primitives/spline.dart';
 import 'package:fis_measure/process/primitives/straightline.dart';
 import 'package:fis_measure/process/primitives/trace.dart';
@@ -170,7 +171,7 @@ class MeasureItemFactory {
 
     // Specific
     _singleton._register(MeasureTypes.Afi, Afi.createAfi);
-    _singleton._register(MeasureTypes.HR, StraightLine.createHeartRate);
+    _singleton._register(MeasureTypes.HR, SingleStraightLine.createHeartRate);
     _singleton._register(MeasureTypes.HipOneRay, TwoRay.createTwoRay);
     _singleton._register(MeasureTypes.HipTwoRay, ThreeRay.createThreeRay);
     _singleton._register(

+ 2 - 1
lib/process/items/item.dart

@@ -88,7 +88,8 @@ abstract class MeasureItem<T extends MeasureItemFeature> extends IMeasureItem {
     bool result = false;
     if (state == ItemStates.waiting ||
         state == ItemStates.running ||
-        state == ItemStates.finished) {
+        state == ItemStates.finished ||
+        state == ItemStates.idle) {
       switch (args.pointType) {
         case PointInfoType.mouseUp:
         case PointInfoType.mouseDown:

+ 163 - 0
lib/process/primitives/single_straightline.dart

@@ -0,0 +1,163 @@
+import 'dart:ui';
+
+import 'package:fis_measure/interfaces/date_types/point.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/items/types.dart';
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:fis_measure/process/calcuators/heart_rate.dart';
+import 'package:fis_measure/process/items/item.dart';
+import 'package:fis_measure/utils/canvas.dart';
+import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
+import 'package:fis_measure/view/gesture/positioned_cursor.dart';
+import 'package:get/get.dart';
+import 'package:vid/us/vid_us_mode.dart';
+import '../items/item_feature.dart';
+
+/// 只绘制一次直线,即会自动开始,不会自动结束
+class SingleStraightLine extends MeasureItem<SingleStraightLineFeature> {
+  late final mouseState = Get.find<IMouseState>();
+  SingleStraightLine(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
+
+  static SingleStraightLine createHeartRate(ItemMeta meta,
+      [IMeasureItem? parent]) {
+    SingleStraightLine straightLine = SingleStraightLine(meta, parent);
+    straightLine.calculator = HeartRateCal(straightLine);
+    final point = DPoint(0, 0);
+    straightLine.feature = StraightLineHeartRateFeature(
+        straightLine, point, point, straightLine.doCalculate,
+        ifHorizontal: false);
+    print('SingleStraightLine.createHeartRate');
+    return straightLine;
+  }
+
+  @override
+  bool onExecuteMouse(PointInfo args) {
+    if (state == ItemStates.waiting) {
+      startMeasure(args);
+    } else if (state == ItemStates.running) {
+      if (args.pointType == PointInfoType.mouseUp) return false;
+      feature?.endPoint = args;
+      doCalculate();
+      if (args.pointType == PointInfoType.mouseDown) {
+        state = ItemStates.idle;
+
+        ///重置十字样式
+        mouseState.crossIndicatorStyleChanged
+            .emit(this, CrossIndicatorStyle.nomal);
+      }
+    } else if (state == ItemStates.idle) {
+      if (args.pointType == PointInfoType.mouseDown) {
+        feature?.startPoint = args;
+        feature?.endPoint = args;
+        state = ItemStates.running;
+
+        ///设置十字样式
+        mouseState.crossIndicatorStyleChanged
+            .emit(this, CrossIndicatorStyle.vertical);
+      }
+    }
+    return true;
+  }
+
+  @override
+  bool onExecuteTouch(PointInfo args) {
+    //TODO
+    return true;
+  }
+
+  void startMeasure(PointInfo args) {
+    final point = DPoint(0, 0);
+    if (args.hostVisualArea != null) {
+      handleTissueTM(args.hostVisualArea!.mode.modeType, point);
+      feature!.hostVisualArea = args.hostVisualArea;
+    }
+    state = ItemStates.idle;
+  }
+
+  /// 处理TissueTimeMotion模式
+  void handleTissueTM(VidUsModeType mode, DPoint point) {
+    if (mode == VidUsModeType.TissueTM || mode == VidUsModeType.Doppler) {
+      switch (meta.measureType) {
+        case MeasureTypes.HR:
+          mouseState.crossIndicatorStyleChanged
+              .emit(this, CrossIndicatorStyle.vertical);
+          break;
+        default:
+      }
+    } else {
+      feature = SingleStraightLineFeature(this, point, point);
+    }
+  }
+}
+
+class SingleStraightLineFeature extends MeasureItemFeature {
+  SingleStraightLineFeature(
+    IMeasureItem refItem,
+    DPoint startPoint,
+    DPoint endPoint,
+  ) : super(refItem) {
+    innerPoints.add(startPoint);
+    innerPoints.add(endPoint);
+  }
+
+  /// 起点
+  DPoint get startPoint => innerPoints[0];
+  set startPoint(DPoint value) => innerPoints[0] = value;
+
+  /// 终点
+  DPoint get endPoint => innerPoints[1];
+  set endPoint(DPoint value) => innerPoints[1] = value;
+
+  /// 长度
+  double get length => (endPoint - startPoint).length;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (startPoint == endPoint) return;
+
+    var idText = '$id.${refItem.briefAnnotation}';
+    drawId(canvas, size, idText);
+
+    final startOffset = convert2ViewPoint(size, startPoint).toOffset();
+    drawVertex(canvas, startOffset);
+
+    final endOffset = convert2ViewPoint(size, endPoint).toOffset();
+    canvas.drawDashLine(startOffset, endOffset, 1, 10, paintPan);
+    drawVertex(canvas, endOffset, isActive);
+  }
+}
+
+class StraightLineHeartRateFeature extends SingleStraightLineFeature {
+  StraightLineHeartRateFeature(
+      IMeasureItem refItem, DPoint startPoint, DPoint endPoint, this.calculate,
+      {this.ifHorizontal = true})
+      : super(refItem, startPoint, endPoint);
+
+  ///心脏周期
+  int heartCycle = 1;
+  final bool ifHorizontal;
+  final Function calculate;
+  void setHeartRate(int cycle) {
+    heartCycle = cycle;
+    calculate();
+  }
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (startPoint == endPoint) return;
+    var idText = '$id';
+    drawId(canvas, size, idText);
+    final startOffset = convert2ViewPoint(size, startPoint).toOffset();
+    final endOffset = convert2ViewPoint(size, endPoint).toOffset();
+    if (ifHorizontal) {
+      drawMark(canvas, startOffset);
+      drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
+    } else {
+      drawMark(canvas, startOffset, false, ifHorizontal);
+      drawMark(
+          canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
+    }
+  }
+}

+ 0 - 47
lib/process/primitives/straightline.dart

@@ -58,12 +58,6 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
     return sraightLine;
   }
 
-  static StraightLine createHeartRate(ItemMeta meta, [IMeasureItem? parent]) {
-    StraightLine sraightLine = StraightLine(meta, parent);
-    sraightLine.calculator = HeartRateCal(sraightLine);
-    return sraightLine;
-  }
-
   @override
   bool onExecuteMouse(PointInfo args) {
     if (state == ItemStates.finished) {
@@ -166,13 +160,6 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
           mouseState.crossIndicatorStyleChanged
               .emit(this, CrossIndicatorStyle.vertical);
           break;
-        case MeasureTypes.HR:
-          feature = StraightLineHeartRateFeature(
-              this, point, point, doCalculate,
-              ifHorizontal: false);
-          mouseState.crossIndicatorStyleChanged
-              .emit(this, CrossIndicatorStyle.vertical);
-          break;
         default:
       }
     } else {
@@ -243,40 +230,6 @@ class StraightLineTimeMotionFeature extends StraightLineFeature {
   }
 }
 
-class StraightLineHeartRateFeature extends StraightLineFeature {
-  StraightLineHeartRateFeature(
-      IMeasureItem refItem, DPoint startPoint, DPoint endPoint, this.calculate,
-      {this.ifHorizontal = true})
-      : super(refItem, startPoint, endPoint);
-
-  ///心脏周期
-  int heartCycle = 1;
-  final bool ifHorizontal;
-  final Function calculate;
-  void setHeartRate(int cycle) {
-    heartCycle = cycle;
-    calculate();
-  }
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    if (startPoint == endPoint) return;
-    var idText = '$id';
-    drawId(canvas, size, idText);
-
-    final startOffset = convert2ViewPoint(size, startPoint).toOffset();
-    final endOffset = convert2ViewPoint(size, endPoint).toOffset();
-    if (ifHorizontal) {
-      drawMark(canvas, startOffset);
-      drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
-    } else {
-      drawMark(canvas, startOffset, false, ifHorizontal);
-      drawMark(
-          canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
-    }
-  }
-}
-
 class StraightLineSlopeFeature extends StraightLineFeature {
   StraightLineSlopeFeature(
       IMeasureItem refItem, DPoint startPoint, DPoint endPoint)

+ 17 - 9
lib/view/measure/combo_widget.dart

@@ -1,5 +1,5 @@
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
-import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:fis_measure/process/primitives/single_straightline.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
 import 'package:fis_theme/theme.dart';
@@ -16,25 +16,33 @@ class _SpecialComboState extends FState<SpecialCombo> {
   final application = Get.find<IApplication>();
 
   late final item = application.activeMeasureItem!;
-  late int selectedIndex = 0;
+  late int selectedIndex = 1;
 
   FWidget buildHRButton(int index) {
     return FInkWell(
       onTap: () {
         final hRFeature = item.feature as StraightLineHeartRateFeature;
         hRFeature.setHeartRate(index);
+        application.updateRenderReady.emit(this, null);
         setState(() {
           selectedIndex = index;
         });
       },
       child: FContainer(
-        color: selectedIndex == index ? Colors.greenAccent : Colors.transparent,
-        margin: const EdgeInsets.symmetric(horizontal: 11),
+        decoration: BoxDecoration(
+          color:
+              selectedIndex == index ? Colors.greenAccent : Colors.transparent,
+          border: Border.all(color: Colors.grey),
+          borderRadius: BorderRadius.circular(5),
+        ),
+        margin: const EdgeInsets.symmetric(horizontal: 11, vertical: 5),
         padding: const EdgeInsets.all(8),
-        child: FText(
-          index.toString(),
-          style: const TextStyle(
-            color: Colors.white,
+        child: FCenter(
+          child: FText(
+            index.toString(),
+            style: const TextStyle(
+              color: Colors.white,
+            ),
           ),
         ),
       ),
@@ -88,7 +96,7 @@ class _SpecialComboState extends FState<SpecialCombo> {
               crossAxisCount: 2,
               childAspectRatio: 3,
               children: [1, 2, 3, 4, 5].map((e) {
-                return FCenter(child: buildHRButton(e));
+                return buildHRButton(e);
               }).toList(),
             ),
           ],