瀏覽代碼

add(measure): 新增组合测量项 残余尿 RUV

gavin.chen 2 年之前
父節點
當前提交
8d9ed45214

+ 3 - 0
lib/interfaces/process/items/types.dart

@@ -34,6 +34,9 @@ class MeasureTypes {
   /// A/B比值
   static const String ABRatio = "A/B Ratio";
 
+  /// 残余尿
+  static const String ResidualUrine = "RUV";
+
   /// 折线多边形测面积周长
   static const String AreaPerimeterPolyline = "AreaPerimeterPolyline";
 

+ 2 - 1
lib/measure_page_test.dart

@@ -344,7 +344,8 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
     MeasureTypes.AreaPerimeterPolyline,
     MeasureTypes.AreaPerimeterSpline,
     MeasureTypes.Stenosis,
-    MeasureTypes.ABRatio
+    MeasureTypes.ABRatio,
+    MeasureTypes.ResidualUrine
   ];
 
   final scrollController = ScrollController();

+ 13 - 0
lib/process/calcuators/formulas/Urology.dart

@@ -0,0 +1,13 @@
+// ignore_for_file:  constant_identifier_names
+
+import 'dart:math' as math;
+
+import 'package:fis_measure/interfaces/date_types/point.dart';
+
+class UrologyFormulas {
+  /// 计算残余尿
+  static double calcRUV(double d1, double d2) {
+    double ruv = d1 * d2 * 5.9 - 14.9;
+    return ruv < 0 ? 0 : ruv;
+  }
+}

+ 47 - 0
lib/process/calcuators/residual_urine.dart

@@ -0,0 +1,47 @@
+import 'package:fis_measure/interfaces/process/calculators/output.dart';
+import 'package:fis_measure/interfaces/process/calculators/values.dart';
+import 'package:fis_measure/process/calcuators/formulas/Urology.dart';
+import 'package:fis_measure/process/calcuators/formulas/general.dart';
+import 'package:fis_measure/process/primitives/combos/two_area.dart';
+import 'package:fis_measure/process/primitives/combos/two_straightline.dart';
+import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:fis_measure/process/primitives/trace.dart';
+
+import 'calculator.dart';
+
+class ResidualUrineCal extends Calculator<TwoStraightLine, double> {
+  ResidualUrineCal(TwoStraightLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final x = _pickChildValue(ref.x);
+    final y = _pickChildValue(ref.y);
+
+    final feature = ref.feature!;
+    final viewport = feature.hostVisualArea!.viewport!;
+
+    if (x != null && y != null) {
+      final value = UrologyFormulas.calcRUV(
+        x,
+        y,
+      );
+      updateFloatValue(value);
+    }
+  }
+
+  double? _pickChildValue(StraightLine item) {
+    if (item.calculator == null) return null;
+    ValueBase? value;
+    if (item.measuredFeatures.isNotEmpty) {
+      value = item.measuredFeatures.first.value;
+    } else if (item.feature != null) {
+      value = item.feature!.value;
+    }
+    if (value != null) {
+      return (value as FloatValue).value ?? 0;
+    }
+    return null;
+  }
+}

+ 3 - 0
lib/process/items/factory.dart

@@ -4,6 +4,7 @@ import 'package:fis_measure/interfaces/process/items/types.dart';
 import 'package:fis_measure/process/items/item.dart';
 import 'package:fis_measure/process/primitives/combos/lwh_straightline.dart';
 import 'package:fis_measure/process/primitives/combos/two_area.dart';
+import 'package:fis_measure/process/primitives/combos/two_straightline.dart';
 import 'package:fis_measure/process/primitives/ellipse.dart';
 import 'package:fis_measure/process/primitives/polyline.dart';
 import 'package:fis_measure/process/primitives/spline.dart';
@@ -75,6 +76,8 @@ class MeasureItemFactory {
     _singleton._register(
         MeasureTypes.Stenosis, TwoArea.crateStenosis, "TwoArea");
     _singleton._register(MeasureTypes.ABRatio, TwoArea.crateABRatio, "TwoArea");
+    _singleton._register(MeasureTypes.ResidualUrine, TwoStraightLine.createRUV,
+        "TwoStraightLine");
 
     //Ellipse
     _singleton._register(

+ 84 - 0
lib/process/primitives/combos/two_straightline.dart

@@ -0,0 +1,84 @@
+import 'dart:ui';
+
+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/a_b_ratio.dart';
+import 'package:fis_measure/process/calcuators/residual_urine.dart';
+import 'package:fis_measure/process/calcuators/stenosis.dart';
+import 'package:fis_measure/process/calcuators/volume.dart';
+import 'package:fis_measure/process/items/item_feature.dart';
+import 'package:fis_measure/process/items/top_item.dart';
+import 'package:fis_measure/process/items/top_item_feature.dart';
+import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:fis_measure/process/primitives/trace.dart';
+
+class TwoStraightLine extends TopMeasureItem<TwoStraightLineFeature> {
+  static const String _xKey = "X";
+  static const String _yKey = "Y";
+
+  late final StraightLine x;
+  late final StraightLine y;
+
+  TwoStraightLine(ItemMeta meta) : super(meta) {
+    final metaX = meta.getChildByName(_xKey)!;
+    final metaY = meta.getChildByName(_yKey)!;
+    x = StraightLine.createDistance(metaX, this);
+    y = StraightLine.createDistance(metaY, this);
+    childItems.add(x);
+    childItems.add(y);
+  }
+
+  @override
+  bool onExecuteMouse(PointInfo args) {
+    if (args.pointType == PointInfoType.mouseDown) {
+      if (feature == null) {
+        feature = TwoStraightLineFeature(this);
+        listenChildrenUpdate();
+      }
+      if (childrenAllDone) {
+        workingChild.clear();
+      }
+    }
+    feature?.hostVisualArea = args.hostVisualArea;
+    final result = workingChild.execute(args);
+    doCalculate();
+    return result;
+  }
+
+  @override
+  bool onExecuteTouch(PointInfo args) {
+    return workingChild.execute(args);
+  }
+
+  @override
+  void onCancelingOnce() {}
+
+  static TwoStraightLine createRUV(ItemMeta meta, [IMeasureItem? parent]) {
+    if (meta.measureType != MeasureTypes.ResidualUrine ||
+        meta.multiMethod != "TwoStraightLine") {
+      throw ArgumentError();
+    }
+    var twoStraightline = TwoStraightLine(meta);
+    twoStraightline.calculator = ResidualUrineCal(twoStraightline);
+
+    return twoStraightline;
+  }
+}
+
+class TwoStraightLineFeature extends TopMeasureItemFeature {
+  TwoStraightLineFeature(
+    ITopMeasureItem refItem,
+  ) : super(refItem);
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    for (var item in refItem.childItems) {
+      for (var feature in item.measuredFeatures) {
+        feature.paint(canvas, size);
+      }
+      item.feature?.paint(canvas, size);
+    }
+  }
+}

+ 28 - 0
lib/process/workspace/application.dart

@@ -519,6 +519,34 @@ class Application implements IApplication {
       );
       return;
     }
+    if (name == MeasureTypes.ResidualUrine) {
+      childBuild(String name) {
+        return ItemMeta(
+          name,
+          description: name,
+          outputs: [
+            ItemOutputMeta("Distance", "Distance", VidUsUnit.cm),
+          ],
+        );
+      }
+
+      activeMeasureItem = MeasureItemFactory.createItem(
+        ItemMeta(
+          MeasureTypes.ResidualUrine,
+          measureType: MeasureTypes.ResidualUrine,
+          description: MeasureTypes.ResidualUrine,
+          outputs: [
+            ItemOutputMeta("RUV", "RUV", VidUsUnit.ml),
+          ],
+          multiMethod: "TwoStraightLine",
+          childItems: [
+            childBuild("X"),
+            childBuild("Y"),
+          ],
+        ),
+      );
+      return;
+    }
 
     if (name == MeasureTypes.AreaPerimeterEllipse) {
       activeMeasureItem = MeasureItemFactory.createItem(