Quellcode durchsuchen

支持VolumeTwoDistance

melon.yin vor 2 Jahren
Ursprung
Commit
a0f5c33db3

+ 8 - 0
lib/interfaces/process/calculators/values.dart

@@ -23,6 +23,14 @@ abstract class ValueBase {
 
   /// 目标单位
   VidUsUnit get targetUnit => meta.unit;
+
+  double? pickFloat() {
+    if (this is FloatValue) {
+      final f = (this as FloatValue).value;
+      return f;
+    }
+    return null;
+  }
 }
 
 abstract class TypedValueBase<T> extends ValueBase {

+ 1 - 0
lib/item_create_test.dart

@@ -105,6 +105,7 @@ class TestItems {
     MeasureTerms.CervixL,
     MeasureTerms.CervixW,
     MeasureTerms.CervixH,
+    "Tumor Cervix",
   ];
 
   static final C_DISTANCE_ITEMS = [

+ 1 - 1
lib/process/calcuators/calculator.dart

@@ -92,7 +92,7 @@ abstract class Calculator<T extends IMeasureItem, TValue>
   }
 
   @protected
-  TF? findBaselineFeatue<TF extends MeasureItemFeature>(MeasureItem child) {
+  TF? findChildFeature<TF extends MeasureItemFeature>(MeasureItem child) {
     if (child.measuredFeatures.isNotEmpty) {
       return child.measuredFeatures.first as TF;
     }

+ 6 - 6
lib/process/calcuators/curve.dart

@@ -1,6 +1,6 @@
 import 'package:fis_measure/interfaces/date_types/point.dart';
 import 'package:fis_measure/interfaces/process/items/terms.dart';
-import 'package:fis_measure/process/primitives/curve_abstract.dart';
+import 'package:fis_measure/process/primitives/area_abstract.dart';
 import 'package:fis_measure/process/primitives/ellipse.dart';
 import 'package:fis_measure/process/primitives/trace.dart';
 
@@ -13,15 +13,15 @@ class AreaPerimeterEllipseCal extends Calculator<Ellipse, double> {
   void calculate() {
     if (ref.feature == null) return;
 
-    final feature = ref.feature!;
+    final feature = ref.feature! as EllipseFeature;
     final viewport = feature.hostVisualArea!.viewport!;
 
     for (var output in ref.meta.outputs) {
       if (output.name == MeasureTerms.Perimeter) {
-        var value = ref.feature!.getCircumference(viewport.convertBoundary);
+        var value = feature.getCircumference(viewport.convertBoundary);
         feature.updateFloatValue(output, value, output.unit);
       } else if (output.name == MeasureTerms.Area) {
-        var value = ref.feature!.getArea(viewport.convertBoundary);
+        var value = feature.getArea(viewport.convertBoundary);
         feature.updateFloatValue(output, value, output.unit);
       }
     }
@@ -102,8 +102,8 @@ class AreaPerimeterCal extends Calculator<Trace, double> {
   }
 }
 
-class CurveLengthCal extends Calculator<CurveAbstract, double> {
-  CurveLengthCal(CurveAbstract ref) : super(ref);
+class CurveLengthCal extends Calculator<AreaItemAbstract, double> {
+  CurveLengthCal(AreaItemAbstract ref) : super(ref);
 
   @override
   void calculate() {

+ 2 - 2
lib/process/calcuators/depth2baseline.dart

@@ -14,8 +14,8 @@ class DistanceToRayCal extends Calculator<DepthToBaseLine, double> {
     if (ref.feature == null) return;
 
     final feature = ref.feature!;
-    final depthFeature = findBaselineFeatue<LocationFeature>(ref.depth);
-    final baselineFeature = findBaselineFeatue<RayFeature>(ref.baseline);
+    final depthFeature = findChildFeature<LocationFeature>(ref.depth);
+    final baselineFeature = findChildFeature<RayFeature>(ref.baseline);
     if (depthFeature == null || baselineFeature == null) return;
 
     final depthLocation = depthFeature.point;

+ 25 - 0
lib/process/calcuators/formulas/general.dart

@@ -8,6 +8,31 @@ class GeneralFormulas {
   /// Volume:1/6 x π
   static const double VolumeCofficient = math.pi / 6.0;
 
+  /// 1/6 x π x D1^2 x D2 (D1 > D2)
+  ///
+  /// 1/6 x π x D1 x D2^2 (D1 ≤ D2)
+  ///
+  /// return unit: cm³</returns>
+  static double volumeTwoLine(double d1, double d2, [bool useBigValue = true]) {
+    double volume = 0;
+    if (!doubleAlmostEquals(d1, 0) && !doubleAlmostEquals(d2, 0)) {
+      if (useBigValue) {
+        if (d1 > d2) {
+          volume = d1 * d1 * d2 * math.pi / 6.0;
+        } else {
+          volume = d1 * d2 * d2 * math.pi / 6.0;
+        }
+      } else {
+        if (d1 > d2) {
+          volume = d2 * d2 * d1 * math.pi / 6.0;
+        } else {
+          volume = d1 * d1 * d2 * math.pi / 6.0;
+        }
+      }
+    }
+    return volume;
+  }
+
   /// 带比率系数算体积
   ///
   /// [coefficient] 比率系数

+ 42 - 0
lib/process/calcuators/two_distance.dart

@@ -1,9 +1,12 @@
 import 'package:fis_measure/interfaces/process/calculators/values.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
 import 'package:fis_measure/process/calcuators/formulas/urology.dart';
 import 'package:fis_measure/process/primitives/combos/two_straightline.dart';
 import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:vid/us/vid_us_unit.dart';
 
 import 'calculator.dart';
+import 'formulas/general.dart';
 
 class TwoDistanceCalBase extends Calculator<TwoStraightLine, double> {
   TwoDistanceCalBase(TwoStraightLine ref) : super(ref);
@@ -50,3 +53,42 @@ class ResidualUrineCal extends Calculator<TwoStraightLine, double> {
     return null;
   }
 }
+
+class TwoDistanceVolumeCal extends Calculator<TwoStraightLine, double> {
+  TwoDistanceVolumeCal(TwoStraightLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final f1 = findChildFeature(ref.child1);
+    final f2 = findChildFeature(ref.child2);
+    if (f1 == null || f2 == null) return;
+
+    final feature = ref.feature!;
+
+    final val1 = f1.value?.pickFloat() ?? 0;
+    final val2 = f2.value?.pickFloat() ?? 0;
+
+    final unitY = f1.hostVisualArea!.viewport!.yUnit;
+
+    for (var ouput in ref.meta.outputs) {
+      if (ouput.name == MeasureTerms.Volume) {
+        var volume = GeneralFormulas.volumeTwoLine(val1, val2);
+        final unit = unitY == VidUsUnit.cm ? VidUsUnit.cm3 : VidUsUnit.None;
+        feature.updateFloatValue(
+          ouput,
+          roundDouble(volume, ouput.fractionalDigits),
+          unit,
+        );
+      } else if (ouput.name == MeasureTerms.AvgDistance) {
+        double avg = (val1 + val2) / 2;
+        feature.updateFloatValue(
+          ouput,
+          roundDouble(avg, ouput.fractionalDigits),
+          unitY,
+        );
+      }
+    }
+  }
+}

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

@@ -82,6 +82,9 @@ class MeasureItemFactory {
     // Three StraightLine
     _singleton._register(
         MeasureTypes.VolumeThreeDistance, LWHStraightLine.createVolume);
+
+    _singleton._register(
+        MeasureTypes.VolumeTwoDistance, TwoStraightLine.createVolume);
     _singleton._register(MeasureTypes.VolumeEllipse, Ellipse.createVolume);
 
     // Two Area

+ 4 - 4
lib/process/primitives/curve_abstract.dart → lib/process/primitives/area_abstract.dart

@@ -4,9 +4,9 @@ import 'package:fis_measure/interfaces/process/items/item_metas.dart';
 import 'package:fis_measure/process/items/item.dart';
 import 'package:fis_measure/process/items/item_feature.dart';
 
-abstract class CurveAbstract extends MeasureItem<CurveAbstractFeature> {
+abstract class AreaItemAbstract extends MeasureItem<AreaItemFeatureAbstract> {
   bool _isClosed = true;
-  CurveAbstract(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
+  AreaItemAbstract(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
 
   bool get isClosed => _isClosed;
   set isClosed(bool val) {
@@ -16,11 +16,11 @@ abstract class CurveAbstract extends MeasureItem<CurveAbstractFeature> {
   }
 }
 
-abstract class CurveAbstractFeature extends MeasureItemFeature {
+abstract class AreaItemFeatureAbstract extends MeasureItemFeature {
   double _splineTension = 0.0;
   bool _isClosed = true;
 
-  CurveAbstractFeature(CurveAbstract refItem) : super(refItem) {
+  AreaItemFeatureAbstract(AreaItemAbstract refItem) : super(refItem) {
     isClosed = refItem.isClosed;
   }
 

+ 41 - 5
lib/process/primitives/combos/area_straightline.dart

@@ -1,23 +1,26 @@
+import 'package:fis_measure/interfaces/process/calculators/values.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/terms.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/calculator.dart';
 import 'package:fis_measure/process/items/factory.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/curve_abstract.dart';
+import 'package:fis_measure/process/primitives/area_abstract.dart';
 import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:vid/us/vid_us_unit.dart';
 
 class AreaStraightLine extends TopMeasureItem<AreaStraightLineFeature> {
-  late final CurveAbstract area;
+  late final AreaItemAbstract area;
   late final StraightLine line;
 
   AreaStraightLine(ItemMeta meta) : super(meta) {
     final metaArea = meta.childItems.firstWhere(
         (e) => e.measureType.startsWith(MeasureTypes.AreaPerimeter));
     final metaLine = meta.getChildByType(MeasureTypes.Distance)!;
-    area = MeasureItemFactory.createItem(metaArea, this) as CurveAbstract;
+    area = MeasureItemFactory.createItem(metaArea, this) as AreaItemAbstract;
     line = StraightLine.createDistance(metaLine, this);
     childItems.add(area);
     childItems.add(line);
@@ -36,7 +39,9 @@ class AreaStraightLine extends TopMeasureItem<AreaStraightLineFeature> {
     }
     feature?.hostVisualArea = args.hostVisualArea;
     final result = workingChild.execute(args);
-    doCalculate();
+    if (result) {
+      doCalculate();
+    }
     return result;
   }
 
@@ -46,6 +51,9 @@ class AreaStraightLine extends TopMeasureItem<AreaStraightLineFeature> {
   }
 
   static AreaStraightLine createVolume(ItemMeta meta, [IMeasureItem? parent]) {
+    if (meta.measureType != MeasureTypes.AreaStraightLine) {
+      throw ArgumentError();
+    }
     final areaStraightLine = AreaStraightLine(meta);
     areaStraightLine.calculator = AreaStraightLineVolumeCal(areaStraightLine);
     return areaStraightLine;
@@ -63,6 +71,34 @@ class AreaStraightLineVolumeCal extends Calculator<AreaStraightLine, double> {
 
   @override
   void calculate() {
-    // TODO: implement calculate
+    if (ref.feature == null) return;
+
+    final areaFeature = findChildFeature<AreaItemFeatureAbstract>(ref.area);
+    final lineFeature = findChildFeature<StraightLineFeature>(ref.line);
+    if (areaFeature == null || lineFeature == null) return;
+
+    final feature = ref.feature!;
+
+    double area = 0;
+    for (var value in areaFeature.values) {
+      if (value.name == MeasureTerms.Area) {
+        area = (value as FloatValue).value ?? 0;
+      }
+    }
+    double height = 0;
+    if (lineFeature.value != null) {
+      height = (lineFeature.value as FloatValue).value ?? 0;
+    }
+    var volume = _caleVolume(area, height);
+    final output = ref.meta.outputs.first;
+    feature.updateFloatValue(
+      output,
+      roundDouble(volume, output.fractionalDigits),
+      VidUsUnit.cm3,
+    );
+  }
+
+  static double _caleVolume(double area, double d2) {
+    return 2.0 / 3.0 * area * d2;
   }
 }

+ 3 - 1
lib/process/primitives/combos/depth2baseline.dart

@@ -42,7 +42,9 @@ class DepthToBaseLine extends TopMeasureItem<DepthToBaseLineFeature> {
     }
     feature?.hostVisualArea = args.hostVisualArea;
     final result = workingChild.execute(args);
-    doCalculate();
+    if (result) {
+      doCalculate();
+    }
     return result;
   }
 

+ 3 - 1
lib/process/primitives/combos/lwh_straightline.dart

@@ -44,7 +44,9 @@ class LWHStraightLine extends TopMeasureItem<LWHStraightlineFeature> {
     }
     feature?.hostVisualArea = args.hostVisualArea;
     final result = workingChild.execute(args);
-    doCalculate();
+    if (result) {
+      doCalculate();
+    }
     return result;
   }
 

+ 3 - 1
lib/process/primitives/combos/two_area.dart

@@ -50,7 +50,9 @@ class TwoArea extends TwoLengthAbstract<TwoAreaFeature> {
     }
     feature?.hostVisualArea = args.hostVisualArea;
     final result = workingChild.execute(args);
-    doCalculate();
+    if (result) {
+      doCalculate();
+    }
     return result;
   }
 

+ 11 - 10
lib/process/primitives/combos/two_straightline.dart

@@ -1,19 +1,11 @@
-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/stenosis.dart';
-import 'package:fis_measure/process/calcuators/three_distance.dart';
 import 'package:fis_measure/process/calcuators/two_distance.dart';
-import 'package:fis_measure/process/items/item.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';
 
 import 'two_length.dart';
 
@@ -26,7 +18,7 @@ class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
     final metaX = meta.childItems[0];
     final metaY = meta.childItems[1];
 
-    if (ifVertical) {
+    if (!ifVertical) {
       x = StraightLine.createDistance(metaX, this);
       y = StraightLine.createDistance(metaY, this);
     } else {
@@ -56,7 +48,9 @@ class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
     }
     feature?.hostVisualArea = args.hostVisualArea;
     final result = workingChild.execute(args);
-    doCalculate();
+    if (result) {
+      doCalculate();
+    }
     return result;
   }
 
@@ -113,6 +107,13 @@ class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
 
     return twoStraightline;
   }
+
+  static TwoStraightLine createVolume(ItemMeta meta, [IMeasureItem? parent]) {
+    var twoStraightline = TwoStraightLine(meta);
+    twoStraightline.calculator = TwoDistanceVolumeCal(twoStraightline);
+
+    return twoStraightline;
+  }
 }
 
 class TwoStraightLineFeature extends TopMeasureItemFeature {

+ 5 - 7
lib/process/primitives/ellipse.dart

@@ -8,13 +8,11 @@ import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
 import 'package:fis_measure/process/calcuators/curve.dart';
 import 'package:fis_measure/process/calcuators/ellipse.dart';
 import 'package:fis_measure/process/calcuators/formulas/general.dart';
-import 'package:fis_measure/process/calcuators/three_distance.dart';
 import 'package:fis_measure/utils/canvas.dart';
 import 'package:path_drawing/path_drawing.dart';
-import '../items/item.dart';
-import '../items/item_feature.dart';
+import 'area_abstract.dart';
 
-class Ellipse extends MeasureItem<EllipseFeature> {
+class Ellipse extends AreaItemAbstract {
   Ellipse(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
 
   @override
@@ -31,7 +29,7 @@ class Ellipse extends MeasureItem<EllipseFeature> {
       }
     } else if (state == ItemStates.running) {
       if (feature == null) return false;
-      final f = feature!;
+      final f = feature! as EllipseFeature;
       final activeIndex = f.activeIndex;
 
       switch (args.pointType) {
@@ -91,8 +89,8 @@ class Ellipse extends MeasureItem<EllipseFeature> {
   }
 }
 
-class EllipseFeature extends MeasureItemFeature {
-  EllipseFeature(IMeasureItem refItem, DPoint point) : super(refItem) {
+class EllipseFeature extends AreaItemFeatureAbstract {
+  EllipseFeature(Ellipse refItem, DPoint point) : super(refItem) {
     innerPoints.add(point.clone());
     innerPoints.add(point.clone());
     innerPoints.add(point.clone());

+ 4 - 4
lib/process/primitives/polyline.dart

@@ -14,10 +14,10 @@ import 'package:fis_measure/process/items/item_feature.dart';
 import 'package:fis_measure/process/primitives/utils/auto_snap.dart';
 import 'package:fis_measure/utils/canvas.dart';
 
-import 'curve_abstract.dart';
+import 'area_abstract.dart';
 
 /// 折线多边形
-class Polyline extends CurveAbstract with AutoSnapMixin {
+class Polyline extends AreaItemAbstract with AutoSnapMixin {
   Polyline(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
 
   static Polyline createAreaPerimeter(ItemMeta meta, [IMeasureItem? parent]) {
@@ -85,8 +85,8 @@ class Polyline extends CurveAbstract with AutoSnapMixin {
   }
 }
 
-class PolylineFeature extends CurveAbstractFeature {
-  PolylineFeature(CurveAbstract refItem, DPoint point) : super(refItem) {
+class PolylineFeature extends AreaItemFeatureAbstract {
+  PolylineFeature(AreaItemAbstract refItem, DPoint point) : super(refItem) {
     innerPoints.add(point.clone());
     innerPoints.add(point.clone());
   }

+ 4 - 4
lib/process/primitives/spline.dart

@@ -15,10 +15,10 @@ import 'package:fis_measure/process/items/item_feature.dart';
 import 'package:fis_measure/process/primitives/utils/auto_snap.dart';
 import 'package:fis_measure/utils/canvas.dart';
 
-import 'curve_abstract.dart';
+import 'area_abstract.dart';
 
 /// 曲线连线
-class Spline extends CurveAbstract with AutoSnapMixin {
+class Spline extends AreaItemAbstract with AutoSnapMixin {
   Spline(ItemMeta meta, [IMeasureItem? parent]) : super(meta, parent);
 
   static Spline createAreaPerimeter(ItemMeta meta, [IMeasureItem? parent]) {
@@ -83,11 +83,11 @@ class Spline extends CurveAbstract with AutoSnapMixin {
   }
 }
 
-class SplineFeature extends CurveAbstractFeature {
+class SplineFeature extends AreaItemFeatureAbstract {
   static const double _splineTension = 0.5;
   static const double _splineTolerance = 0.05;
 
-  SplineFeature(CurveAbstract refItem, DPoint point) : super(refItem) {
+  SplineFeature(AreaItemAbstract refItem, DPoint point) : super(refItem) {
     innerPoints.add(point.clone());
     innerPoints.add(point.clone());
     splineTension = _splineTension;

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

@@ -55,6 +55,8 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
     if (state == ItemStates.finished) {
       if (args.pointType == PointInfoType.mouseDown) {
         state = ItemStates.waiting;
+      } else {
+        return false;
       }
     }
 

+ 4 - 4
lib/process/primitives/trace.dart

@@ -11,10 +11,10 @@ import 'package:path_drawing/path_drawing.dart';
 
 import '../items/item.dart';
 import '../items/item_feature.dart';
-import 'curve_abstract.dart';
+import 'area_abstract.dart';
 
 /// 手势轨迹图形
-class Trace extends CurveAbstract with AutoSnapMixin {
+class Trace extends AreaItemAbstract with AutoSnapMixin {
   final bool _initialClosed = false;
   PointInfo? _firstPoint;
 
@@ -121,8 +121,8 @@ class Trace extends CurveAbstract with AutoSnapMixin {
   }
 }
 
-class TraceFeature extends CurveAbstractFeature {
-  TraceFeature(CurveAbstract refItem) : super(refItem);
+class TraceFeature extends AreaItemFeatureAbstract {
+  TraceFeature(AreaItemAbstract refItem) : super(refItem);
 
   @override
   void paint(Canvas canvas, Size size) {

+ 1 - 1
lib/view/result/results_panel.dart

@@ -37,7 +37,7 @@ class _MeasureResultPanelState extends State<MeasureResultPanel> {
 
     final child = Container(
       constraints: const BoxConstraints(
-        maxWidth: 200,
+        maxWidth: 300,
         minWidth: 150,
         maxHeight: 400,
       ),