|
@@ -2,11 +2,101 @@
|
|
|
|
|
|
import 'dart:math' as math;
|
|
|
|
|
|
+import 'package:fis_measure/configs/patient.dart';
|
|
|
import 'package:fis_measure/interfaces/date_types/point.dart';
|
|
|
+import 'package:fis_measure/interfaces/enums/species.dart';
|
|
|
|
|
|
class GeneralFormulas {
|
|
|
GeneralFormulas._();
|
|
|
+ static const double VolumeCofficient = math.pi / 6.0;
|
|
|
+
|
|
|
+ static final IGeneralFormulaStrategy _singleton =
|
|
|
+ GlobalPatientConfig.speciesType != SpeciesType.general
|
|
|
+ ? BaseGeneralFormulas()
|
|
|
+ : MouseGeneralFormulas();
|
|
|
+
|
|
|
+ static double volumeTwoLine(double d1, double d2,
|
|
|
+ [bool useBigValue = true]) =>
|
|
|
+ _singleton.volumeTwoLine(d1, d2, useBigValue);
|
|
|
+
|
|
|
+ static double volumeWithCoefficient(
|
|
|
+ double d1, double d2, double d3, double coefficient) =>
|
|
|
+ _singleton.volumeWithCoefficient(d1, d2, d3, coefficient);
|
|
|
+
|
|
|
+ static double countStenosis(double d1, double d2) =>
|
|
|
+ _singleton.countStenosis(d1, d2);
|
|
|
+
|
|
|
+ static bool doubleAlmostEquals(double num1, double num2,
|
|
|
+ [double precision = 0.000001]) =>
|
|
|
+ _singleton.doubleAlmostEquals(num1, num2, precision);
|
|
|
+
|
|
|
+ static double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) =>
|
|
|
+ _singleton.distance2Line(pt1, pt2, pt);
|
|
|
+
|
|
|
+ static double countSlope(DPoint p1, DPoint p2) =>
|
|
|
+ _singleton.countSlope(p1, p2);
|
|
|
+
|
|
|
+ static double countEnvelopeTime(List<DPoint> points) =>
|
|
|
+ _singleton.countEnvelopeTime(points);
|
|
|
+
|
|
|
+ static double countPressure(double v) => _singleton.countPressure(v);
|
|
|
+
|
|
|
+ static double countRI(double ps, double mdEd) => _singleton.countRI(ps, mdEd);
|
|
|
+
|
|
|
+ static double countMaxPG(double v1, double v2) =>
|
|
|
+ _singleton.countMaxPG(v1, v2);
|
|
|
+
|
|
|
+ static double countHR(double timeSpan) => _singleton.countHR(timeSpan);
|
|
|
+
|
|
|
+ static List<double> countVTI(List<DPoint> tracePoints) =>
|
|
|
+ _singleton.countVTI(tracePoints);
|
|
|
+
|
|
|
+ static double svDiam(double diam, double vti) => _singleton.svDiam(diam, vti);
|
|
|
+
|
|
|
+ static double csa(double diam) => _singleton.csa(diam);
|
|
|
|
|
|
+ static double dpDtRatio(DPoint p1, DPoint p2) => _singleton.dpDtRatio(p1, p2);
|
|
|
+
|
|
|
+ static double maxPG(double v1, double v2) => _singleton.maxPG(v1, v2);
|
|
|
+
|
|
|
+ static double area(double d1, double d2) => _singleton.area(d1, d2);
|
|
|
+
|
|
|
+ static double flowVolTAMAX(
|
|
|
+ double flowArea, double tamean, double coefficient) =>
|
|
|
+ _singleton.flowVolTAMAX(flowArea, tamean, coefficient);
|
|
|
+}
|
|
|
+
|
|
|
+abstract class IGeneralFormulaStrategy {
|
|
|
+ double volumeTwoLine(double d1, double d2, [bool useBigValue = true]);
|
|
|
+ double volumeWithCoefficient(
|
|
|
+ double d1,
|
|
|
+ double d2,
|
|
|
+ double d3,
|
|
|
+ double coefficient,
|
|
|
+ );
|
|
|
+ double countStenosis(double d1, double d2);
|
|
|
+
|
|
|
+ bool doubleAlmostEquals(double num1, double num2,
|
|
|
+ [double precision = 0.000001]);
|
|
|
+ double distance2Line(DPoint pt1, DPoint pt2, DPoint pt);
|
|
|
+ double countSlope(DPoint p1, DPoint p2);
|
|
|
+ double countEnvelopeTime(List<DPoint> points);
|
|
|
+ double countPressure(double v);
|
|
|
+ double countRI(double ps, double mdEd);
|
|
|
+ double countMaxPG(double v1, double v2);
|
|
|
+ double countHR(double timeSpan);
|
|
|
+ List<double> countVTI(
|
|
|
+ List<DPoint> tracePoints,
|
|
|
+ );
|
|
|
+ double svDiam(double diam, double vti);
|
|
|
+ double csa(double diam);
|
|
|
+ double dpDtRatio(DPoint p1, DPoint p2);
|
|
|
+ double maxPG(double v1, double v2);
|
|
|
+ double area(double d1, double d2);
|
|
|
+ double flowVolTAMAX(double flowArea, double tamean, double coefficient);
|
|
|
+}
|
|
|
+
|
|
|
+class BaseGeneralFormulas implements IGeneralFormulaStrategy {
|
|
|
/// Volume:1/6 x π
|
|
|
static const double VolumeCofficient = math.pi / 6.0;
|
|
|
|
|
@@ -15,7 +105,8 @@ class GeneralFormulas {
|
|
|
/// 1/6 x π x D1 x D2^2 (D1 ≤ D2)
|
|
|
///
|
|
|
/// return unit: cm³</returns>
|
|
|
- static double volumeTwoLine(double d1, double d2, [bool useBigValue = true]) {
|
|
|
+ @override
|
|
|
+ double volumeTwoLine(double d1, double d2, [bool useBigValue = true]) {
|
|
|
double volume = 0;
|
|
|
if (!doubleAlmostEquals(d1, 0) && !doubleAlmostEquals(d2, 0)) {
|
|
|
if (useBigValue) {
|
|
@@ -38,7 +129,8 @@ class GeneralFormulas {
|
|
|
/// 带比率系数算体积
|
|
|
///
|
|
|
/// [coefficient] 比率系数
|
|
|
- static double volumeWithCoefficient(
|
|
|
+ @override
|
|
|
+ double volumeWithCoefficient(
|
|
|
double d1,
|
|
|
double d2,
|
|
|
double d3,
|
|
@@ -54,7 +146,8 @@ class GeneralFormulas {
|
|
|
}
|
|
|
|
|
|
/// 狭窄率计算
|
|
|
- static double countStenosis(double d1, double d2) {
|
|
|
+ @override
|
|
|
+ double countStenosis(double d1, double d2) {
|
|
|
double residual;
|
|
|
double lumen;
|
|
|
if (d1 > d2) {
|
|
@@ -67,7 +160,8 @@ class GeneralFormulas {
|
|
|
return (1.0 - residual / lumen) * 100;
|
|
|
}
|
|
|
|
|
|
- static bool doubleAlmostEquals(double num1, double num2,
|
|
|
+ @override
|
|
|
+ bool doubleAlmostEquals(double num1, double num2,
|
|
|
[double precision = 0.000001]) {
|
|
|
if (num1.isNaN && num2.isNaN) return true;
|
|
|
return (num1 - num2).abs() <= precision;
|
|
@@ -80,7 +174,8 @@ class GeneralFormulas {
|
|
|
/// [pt2] 线端点2
|
|
|
///
|
|
|
/// [pt] 点
|
|
|
- static double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) {
|
|
|
+ @override
|
|
|
+ double distance2Line(DPoint pt1, DPoint pt2, DPoint pt) {
|
|
|
double dis = 0;
|
|
|
if (pt1.x == pt2.x) {
|
|
|
dis = (pt.x - pt1.x).abs();
|
|
@@ -93,7 +188,8 @@ class GeneralFormulas {
|
|
|
}
|
|
|
|
|
|
///计算斜率
|
|
|
- static double countSlope(DPoint p1, DPoint p2) {
|
|
|
+ @override
|
|
|
+ double countSlope(DPoint p1, DPoint p2) {
|
|
|
if (doubleAlmostEquals(p2.x, p1.x)) return 0;
|
|
|
double vertical = p2.y - p1.y;
|
|
|
double time = (p2.x - p1.x).abs();
|
|
@@ -103,7 +199,8 @@ class GeneralFormulas {
|
|
|
|
|
|
///计算包络时间
|
|
|
///Origin: Vinno.Modules.MeasureModule\Formulas\GeneralFormulas.cs [632:67]
|
|
|
- static double countEnvelopeTime(List<DPoint> points) {
|
|
|
+ @override
|
|
|
+ double countEnvelopeTime(List<DPoint> points) {
|
|
|
if (points.length < 2) return 0;
|
|
|
double startTime = double.maxFinite;
|
|
|
double endTime = -double.maxFinite;
|
|
@@ -123,7 +220,8 @@ class GeneralFormulas {
|
|
|
/// </summary>
|
|
|
/// <param name="v">Unit cm/s</param>
|
|
|
/// <returns>Unit mmHg</returns>
|
|
|
- static double countPressure(double v) {
|
|
|
+ @override
|
|
|
+ double countPressure(double v) {
|
|
|
// The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
|
|
|
double pg = 4.0 * math.pow(v * 0.01, 2);
|
|
|
return pg;
|
|
@@ -136,7 +234,8 @@ class GeneralFormulas {
|
|
|
/// </summary>
|
|
|
/// <param name="ps">Unit cm/s</param>
|
|
|
/// <param name="mdEd">Unit cm/s</param>
|
|
|
- static double countRI(double ps, double mdEd) {
|
|
|
+ @override
|
|
|
+ double countRI(double ps, double mdEd) {
|
|
|
ps = ps.abs();
|
|
|
mdEd = mdEd.abs();
|
|
|
double ri = (ps - mdEd) / ps;
|
|
@@ -152,7 +251,8 @@ class GeneralFormulas {
|
|
|
/// <param name="v1">Unit cm/s</param>
|
|
|
/// <param name="v2">Unit cm/s</param>
|
|
|
/// <returns>Unit mmHg</returns>
|
|
|
- static double countMaxPG(double v1, double v2) {
|
|
|
+ @override
|
|
|
+ double countMaxPG(double v1, double v2) {
|
|
|
// The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
|
|
|
double meanPG =
|
|
|
4.0 * (math.pow(v1 * 0.01, 2) - math.pow(v2 * 0.01, 2)).abs();
|
|
@@ -162,14 +262,16 @@ class GeneralFormulas {
|
|
|
// 计算心率
|
|
|
// TODO: 心脏周期(可配置) DefaultHeartCycle = 2;
|
|
|
// Origin: Vinno.Modules.MeasureModule\Primitives\DopplerTraceBase.cs
|
|
|
- static double countHR(double timeSpan) {
|
|
|
+ @override
|
|
|
+ double countHR(double timeSpan) {
|
|
|
const defaultHeartCycle = 1;
|
|
|
double hr = (defaultHeartCycle * 60 / timeSpan).roundToDouble();
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
// return [VTI,tiEnv,timeAveragedVelocity,pv,meanPG,hr];
|
|
|
- static List<double> countVTI(
|
|
|
+ @override
|
|
|
+ List<double> countVTI(
|
|
|
List<DPoint> tracePoints,
|
|
|
) {
|
|
|
var tiEnv = 0.0;
|
|
@@ -239,7 +341,8 @@ class GeneralFormulas {
|
|
|
/// [vti] `cm`
|
|
|
///
|
|
|
/// return `cm3`
|
|
|
- static double svDiam(double diam, double vti) {
|
|
|
+ @override
|
|
|
+ double svDiam(double diam, double vti) {
|
|
|
double sv = math.pi * math.pow(diam, 2) * vti / 4;
|
|
|
return sv;
|
|
|
}
|
|
@@ -251,7 +354,8 @@ class GeneralFormulas {
|
|
|
/// [diam] `cm`
|
|
|
///
|
|
|
/// return `cm²`
|
|
|
- static double csa(double diam) {
|
|
|
+ @override
|
|
|
+ double csa(double diam) {
|
|
|
double csa = math.pi * math.pow(diam, 2) / 4;
|
|
|
return csa;
|
|
|
}
|
|
@@ -259,7 +363,8 @@ class GeneralFormulas {
|
|
|
/// CW/PW Mode: dp/dt = (4* V2 * V2 - 4 * V1 * V1)/ (T2 - T1)
|
|
|
///
|
|
|
/// return `mmHg/s`
|
|
|
- static double dpDtRatio(DPoint p1, DPoint p2) {
|
|
|
+ @override
|
|
|
+ double dpDtRatio(DPoint p1, DPoint p2) {
|
|
|
double dp = maxPG(p2.y, p1.y);
|
|
|
double dt = (p2.x - p1.x).abs();
|
|
|
double result = dp / dt;
|
|
@@ -273,7 +378,8 @@ class GeneralFormulas {
|
|
|
/// [v2] `cm/s`
|
|
|
///
|
|
|
/// reutrn `mmHg`
|
|
|
- static double maxPG(double v1, double v2) {
|
|
|
+ @override
|
|
|
+ double maxPG(double v1, double v2) {
|
|
|
// The velocity is in cm/s, but it should be m/s in this formula, so divide it by 100.
|
|
|
double meanPG =
|
|
|
4.0 * (math.pow(v1 * 0.01, 2) - math.pow(v2 * 0.01, 2)).abs();
|
|
@@ -287,7 +393,8 @@ class GeneralFormulas {
|
|
|
/// [d2] `cm`
|
|
|
///
|
|
|
/// return `cm²`
|
|
|
- static double area(double d1, double d2) {
|
|
|
+ @override
|
|
|
+ double area(double d1, double d2) {
|
|
|
double area = 0;
|
|
|
if (!doubleAlmostEquals(d1, 0) && !doubleAlmostEquals(d2, 0)) {
|
|
|
if ((d1 < 0.001 * d2) || (d2 < 0.001 * d1)) {
|
|
@@ -310,8 +417,8 @@ class GeneralFormulas {
|
|
|
/// [coefficient] `[0.5,1.0]`
|
|
|
///
|
|
|
/// return `cm³/s`
|
|
|
- static double flowVolTAMAX(
|
|
|
- double flowArea, double tamean, double coefficient) {
|
|
|
+ @override
|
|
|
+ double flowVolTAMAX(double flowArea, double tamean, double coefficient) {
|
|
|
if (coefficient < 0.5 || coefficient > 1.0) {
|
|
|
return double.nan;
|
|
|
}
|
|
@@ -319,3 +426,5 @@ class GeneralFormulas {
|
|
|
return flowVol;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+class MouseGeneralFormulas extends BaseGeneralFormulas {}
|