carotid_imt.dart 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import 'dart:convert';
  2. import 'dart:ui';
  3. import 'package:fis_measure/interfaces/date_types/point.dart';
  4. import 'package:fis_measure/process/primitives/carotid_imt.dart';
  5. import 'package:fis_measure/utils/js_utils.dart'
  6. if (dart.library.io) 'package:fis_measure/utils/js_utils4native.dart'
  7. if (dart.library.html) 'package:fis_measure/utils/js_utils.dart';
  8. import 'package:vid/us/vid_us_unit.dart';
  9. import 'calculator.dart';
  10. class CarotidCal extends Calculator<CarotidIMT, double> {
  11. CarotidCal(CarotidIMT ref, this.type) : super(ref);
  12. String type = '';
  13. @override
  14. void calculate() {
  15. if (ref.feature == null) return;
  16. final p1 = ref.feature!.startPoint;
  17. final p2 = ref.feature!.endPoint;
  18. //左上顶点
  19. final leftTopPoint =
  20. DPoint(p1.x < p2.x ? p1.x : p2.x, p1.y < p2.y ? p1.y : p2.y);
  21. //右下顶点
  22. final rightBottomPoint =
  23. DPoint(p1.x > p2.x ? p1.x : p2.x, p1.y > p2.y ? p1.y : p2.y);
  24. //图片尺寸
  25. final imageSize = ref.application.carotid2DSize;
  26. //画布尺寸
  27. final canavsSize = ref.application.displaySize;
  28. //图像缩放比
  29. final imageScale = ref.application.displayScaleRatio;
  30. //标准画布尺寸
  31. final stdCanavsSize =
  32. Size(canavsSize.width / imageScale, canavsSize.height / imageScale);
  33. //Vid图像左上顶点的像素坐标
  34. final imageLeftTopPoint = DPoint(
  35. (stdCanavsSize.width - imageSize.width) / 2,
  36. (stdCanavsSize.height - imageSize.height) / 2);
  37. //Vid图像右下顶点的像素坐标
  38. final imageRightBottomPoint = DPoint(imageLeftTopPoint.x + imageSize.width,
  39. imageLeftTopPoint.y + imageSize.height);
  40. //选区左上顶点的像素坐标
  41. final rectLeftTopPoint = DPoint(stdCanavsSize.width * leftTopPoint.x,
  42. stdCanavsSize.height * leftTopPoint.y);
  43. //选区右下顶点的像素坐标
  44. final rectRightBottomPoint = DPoint(
  45. stdCanavsSize.width * rightBottomPoint.x,
  46. stdCanavsSize.height * rightBottomPoint.y);
  47. /// 在图像外的点改到图像边缘上
  48. if (rectLeftTopPoint.x < imageLeftTopPoint.x) {
  49. rectLeftTopPoint.x = imageLeftTopPoint.x;
  50. }
  51. if (rectLeftTopPoint.x > imageRightBottomPoint.x) {
  52. rectLeftTopPoint.x = imageRightBottomPoint.x;
  53. }
  54. if (rectLeftTopPoint.y < imageLeftTopPoint.y) {
  55. rectLeftTopPoint.y = imageLeftTopPoint.y;
  56. }
  57. if (rectLeftTopPoint.y > imageRightBottomPoint.y) {
  58. rectLeftTopPoint.y = imageRightBottomPoint.y;
  59. }
  60. if (rectRightBottomPoint.x > imageRightBottomPoint.x) {
  61. rectRightBottomPoint.x = imageRightBottomPoint.x;
  62. }
  63. if (rectRightBottomPoint.x < imageLeftTopPoint.x) {
  64. rectRightBottomPoint.x = imageLeftTopPoint.x;
  65. }
  66. if (rectRightBottomPoint.y > imageRightBottomPoint.y) {
  67. rectRightBottomPoint.y = imageRightBottomPoint.y;
  68. }
  69. if (rectRightBottomPoint.y < imageLeftTopPoint.y) {
  70. rectRightBottomPoint.y = imageLeftTopPoint.y;
  71. }
  72. final rectLeft = (rectLeftTopPoint.x - imageLeftTopPoint.x).round();
  73. final rectTop = (rectLeftTopPoint.y - imageLeftTopPoint.y).round();
  74. final rectWidth = (rectRightBottomPoint.x - rectLeftTopPoint.x).round();
  75. final rectHeight = (rectRightBottomPoint.y - rectLeftTopPoint.y).round();
  76. String measureItemType = 'AntMeasureItem';
  77. if (type == 'Ant.CCA IMT') {
  78. measureItemType = 'AntMeasureItem';
  79. } else if (type == 'Post.CCA IMT') {
  80. measureItemType = 'PostMeasureItem';
  81. } else if (type == 'Both.CCA IMT') {
  82. measureItemType = 'AntAndPostMeasureItem';
  83. }
  84. final params =
  85. "{'MeasureItemType':'$measureItemType','IntimaRect':{'Left':$rectLeft,'Top':$rectTop,'Width':$rectWidth,'Height':$rectHeight}}";
  86. String description = "IMT\n Measuring";
  87. updateStringValue(description);
  88. List<Offset> getPointsFromStrList(List pointsStr) {
  89. final points = <Offset>[];
  90. for (var point in pointsStr) {
  91. final xyStr = point.split(',');
  92. points.add(Offset((double.parse(xyStr[0]) + imageLeftTopPoint.x),
  93. (double.parse(xyStr[1]) + imageLeftTopPoint.y)));
  94. }
  95. return points;
  96. }
  97. /// [Carotid] ✅在此处通知 Shell 计算,获取 description,touch/mouse finished 时绘制结果
  98. try {
  99. callShellMethod('getMeasureResult', [params]).callMethod(
  100. 'then',
  101. [
  102. (result) {
  103. final feature = ref.feature!;
  104. // print("getMeasureResult: $result");
  105. if (result == 'error') {
  106. description = "\n Measure failed";
  107. updateStringValue(description);
  108. ref.application.updateRenderReady.emit(this, null);
  109. return;
  110. }
  111. final res = jsonDecode(result);
  112. if (res['ErrorCode'].toString() == "1000") {
  113. if (type != 'Both.CCA IMT') {
  114. description =
  115. "\n Max: ${res['MaxThickness'].toStringAsFixed(2)}mm\n Min: ${res['MinThickness'].toStringAsFixed(2)}mm\n Avg: ${res['AverageThickness'].toStringAsFixed(2)}mm\n SD: ${res['SdThickness'].toStringAsFixed(2)}mm";
  116. } else {
  117. description =
  118. "\n Ant Max: ${res['LowerMeasureResult']['MaxThickness'].toStringAsFixed(2)}mm\n Ant.Min: ${res['LowerMeasureResult']['MinThickness'].toStringAsFixed(2)}mm\n Ant.Avg: ${res['LowerMeasureResult']['AverageThickness'].toStringAsFixed(2)}mm\n Ant.SD: ${res['LowerMeasureResult']['SdThickness'].toStringAsFixed(2)}mm\n Post.Max: ${res['UpperMeasureResult']['MaxThickness'].toStringAsFixed(2)}mm\n Post.Min: ${res['UpperMeasureResult']['MinThickness'].toStringAsFixed(2)}mm\n Post.Avg: ${res['UpperMeasureResult']['AverageThickness'].toStringAsFixed(2)}mm\n Post.SD: ${res['UpperMeasureResult']['SdThickness'].toStringAsFixed(2)}mm";
  119. }
  120. if (type != 'Both.CCA IMT') {
  121. feature.offsetsList
  122. .add(getPointsFromStrList(res['PointLower']));
  123. feature.offsetsList
  124. .add(getPointsFromStrList(res['PointUpper']));
  125. } else {
  126. feature.offsetsList.add(getPointsFromStrList(
  127. res['LowerMeasureResult']['PointLower']));
  128. feature.offsetsList.add(getPointsFromStrList(
  129. res['LowerMeasureResult']['PointUpper']));
  130. feature.offsetsList.add(getPointsFromStrList(
  131. res['UpperMeasureResult']['PointLower']));
  132. feature.offsetsList.add(getPointsFromStrList(
  133. res['UpperMeasureResult']['PointUpper']));
  134. }
  135. } else {
  136. description = "\n Measure failed";
  137. }
  138. updateStringValue(description);
  139. /// [Carotid] ✅在此处通知canvas 重绘结果
  140. ref.application.updateRenderReady.emit(this, null);
  141. },
  142. ],
  143. );
  144. } catch (e) {
  145. updateStringValue("\n Measure failed");
  146. //
  147. }
  148. }
  149. }