Explorar el Código

1、新增周长的LW计算

guanxinyi hace 8 meses
padre
commit
31b65899ac

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

@@ -60,6 +60,7 @@ class GeneralFormulas {
   static double maxPG(double v1, double v2) => _singleton.maxPG(v1, v2);
 
   static double area(double d1, double d2) => _singleton.area(d1, d2);
+  static double perimeter(double d1, double d2) => _singleton.perimeter(d1, d2);
 
   static double flowVolTAMAX(
           double flowArea, double tamean, double coefficient) =>
@@ -100,6 +101,7 @@ abstract class IGeneralFormulaStrategy {
   double maxPG(double v1, double v2);
   double area(double d1, double d2);
   double flowVolTAMAX(double flowArea, double tamean, double coefficient);
+  double perimeter(double d1, double d2);
 
   /// <summary>
   /// Pulastility Index
@@ -461,6 +463,51 @@ class BaseGeneralFormulas implements IGeneralFormulaStrategy {
     ed = ed.abs();
     return (ps + 2 * ed) / 3;
   }
+
+  @override
+  double perimeter(double d1, double d2) {
+    double perimeter = 0.0;
+    if (!almostEquals(d1, 0.0) && !almostEquals(d2, 0.0)) {
+      if (almostEquals(d1, d2)) {
+        // Circle
+        perimeter = d1 * math.pi;
+      } else if (d1 < 0.001 * d2) {
+        // Straight line
+        perimeter = 2.0 * d2;
+      } else if (d2 < 0.001 * d1) {
+        // Straight line
+        perimeter = 2.0 * d1;
+      } else {
+        // Ellipse
+        double a = d1 > d2 ? d1 / 2.0 : d2 / 2.0; // longest half axis
+        double b = d1 < d2 ? d1 / 2.0 : d2 / 2.0; // shortest half axis
+
+        if (a < 0.0001) {
+          // Long axis too short to make computations. Return zero.
+          perimeter = 0.0;
+        } else {
+          // Calculate k, kc
+          double k = math.sqrt(a * a - b * b) / a;
+          double kc2 = 1 - k * k;
+          perimeter = 4.0 * a * ellipseCircum(math.sqrt(kc2), kc2);
+        }
+      }
+    }
+    return perimeter;
+  }
+
+  bool almostEquals(double a, double b, [double epsilon = 1e-10]) {
+    return (a - b).abs() < epsilon;
+  }
+
+  double ellipseCircum(double k, double kc2) {
+    // Placeholder for the EllipseCircum method equivalent.
+    // You can implement the complete elliptic integral of the second kind here
+    // or use an approximation method for ellipse circumference.
+    // For the sake of this example, we will use Ramanujan's approximation.
+    double h = math.pow((k - 1), 2) / math.pow((k + 1), 2);
+    return math.pi * (1 + 3 * h / (10 + math.sqrt(4 - 3 * h)));
+  }
 }
 
 class AnimalsGeneralFormulas extends BaseGeneralFormulas {}

+ 41 - 1
lib/process/calcuators/two_distance.dart

@@ -1,7 +1,6 @@
 import 'package:fis_measure/interfaces/date_types/vector.dart';
 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/cardiac.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';
@@ -251,3 +250,44 @@ class RvStudyCal extends TwoDistanceCalBase {
     }
   }
 }
+
+class AreaPerimeterByLAndWCal extends Calculator<TwoStraightLine, double> {
+  AreaPerimeterByLAndWCal(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;
+
+    var unitY = f1.hostVisualArea!.viewport!.yUnit;
+    if (unitY == VidUsUnit.None) {
+      if (f1.value != null) {
+        unitY = f1.value!.unit;
+      }
+    }
+    for (var ouput in ref.meta.outputs) {
+      if (ouput.name == MeasureTerms.Area) {
+        var area = GeneralFormulas.area(val1, val2);
+        feature.updateFloatValue(
+          ouput,
+          roundDouble(area, ouput.fractionalDigits),
+          unitY,
+        );
+      } else if (ouput.name == MeasureTerms.Perimeter) {
+        var perimeter = GeneralFormulas.perimeter(val1, val2);
+        feature.updateFloatValue(
+          ouput,
+          roundDouble(perimeter, ouput.fractionalDigits),
+          unitY,
+        );
+      }
+    }
+  }
+}

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

@@ -224,6 +224,9 @@ class MeasureItemFactory {
     _singleton._register(
         MeasureTypes.AreaPerimeterTrace, Trace.createAreaPerimeter);
 
+    _singleton._register(MeasureTypes.AreaPerimeterTwoDistance,
+        TwoStraightLine.createAreaPerimeter);
+
     // Area & H
     _singleton._register(
         MeasureTypes.AreaStraightLine, AreaStraightLine.createVolume);

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

@@ -151,6 +151,13 @@ class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
     return twoStraightline;
   }
 
+  static TwoStraightLine createAreaPerimeter(ItemMeta meta,
+      [IMeasureItem? parent]) {
+    var twoStraightline = TwoStraightLine(meta);
+    twoStraightline.calculator = AreaPerimeterByLAndWCal(twoStraightline);
+    return twoStraightline;
+  }
+
   static bool _checkIsModeBelow() {
     if (Get.isRegistered<IApplication>()) {
       final app = Get.find<IApplication>();