urm_shell_measure.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import 'dart:ui' as ui;
  2. import 'package:fis_measure/interfaces/date_types/point.dart';
  3. import 'package:fis_measure/interfaces/enums/items.dart';
  4. import 'package:fis_measure/interfaces/process/items/item.dart';
  5. import 'package:fis_measure/interfaces/process/items/item_metas.dart';
  6. import 'package:fis_measure/interfaces/process/items/types.dart';
  7. import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
  8. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_den_measure.dart';
  9. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_den_vel_measure.dart';
  10. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_density_measure.dart';
  11. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_fractal_dim_measure.dart';
  12. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_hist_measure.dart';
  13. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_perfusion_measure.dart';
  14. import 'package:fis_measure/process/calcuators/urm_calcuators/urm_shell_vel_measure.dart';
  15. import 'package:fis_measure/process/primitives/area_abstract.dart';
  16. import 'package:fis_measure/process/primitives/trace.dart';
  17. import 'package:fis_measure/process/primitives/utils/urm_sharp_copy.dart';
  18. import 'package:fis_measure/utils/canvas.dart';
  19. import 'package:fis_measure/utils/prompt_box.dart';
  20. import 'package:flutter/material.dart';
  21. import 'package:flutter/services.dart';
  22. class URMShellMeasure extends Trace {
  23. URMShellMeasure(super.meta, super.parent);
  24. static URMShellMeasure createURMShellDenMeasure(ItemMeta meta,
  25. [IMeasureItem? parent]) {
  26. URMShellMeasure measureShellDen = URMShellMeasure(meta, parent);
  27. measureShellDen.calculator = URMShellDenMeasureCal(
  28. measureShellDen,
  29. );
  30. return measureShellDen;
  31. }
  32. static URMShellMeasure createURMShellVelMeasure(ItemMeta meta,
  33. [IMeasureItem? parent]) {
  34. URMShellMeasure measureShellVel = URMShellMeasure(meta, parent);
  35. measureShellVel.calculator = URMShellVelMeasureCal(
  36. measureShellVel,
  37. );
  38. return measureShellVel;
  39. }
  40. static URMShellMeasure createURMShellDensityMeasure(ItemMeta meta,
  41. [IMeasureItem? parent]) {
  42. URMShellMeasure measureShellDensity = URMShellMeasure(meta, parent);
  43. measureShellDensity.calculator = URMShellDensityMeasureCal(
  44. measureShellDensity,
  45. );
  46. return measureShellDensity;
  47. }
  48. static URMShellMeasure createURMShellFractalDimMeasure(ItemMeta meta,
  49. [IMeasureItem? parent]) {
  50. URMShellMeasure measureShellFractalDim = URMShellMeasure(meta, parent);
  51. measureShellFractalDim.calculator = URMShellFractalDimMeasureCal(
  52. measureShellFractalDim,
  53. );
  54. return measureShellFractalDim;
  55. }
  56. static URMShellMeasure createURMShellPerfusionMeasure(ItemMeta meta,
  57. [IMeasureItem? parent]) {
  58. URMShellMeasure measureShellPerfusion = URMShellMeasure(meta, parent);
  59. measureShellPerfusion.calculator = URMShellPerfusionMeasureCal(
  60. measureShellPerfusion,
  61. );
  62. return measureShellPerfusion;
  63. }
  64. static URMShellMeasure createURMShellHistMeasure(ItemMeta meta,
  65. [IMeasureItem? parent]) {
  66. URMShellMeasure measureShellHist = URMShellMeasure(meta, parent);
  67. measureShellHist.calculator = URMShellHistMeasureCal(
  68. measureShellHist,
  69. );
  70. return measureShellHist;
  71. }
  72. static URMShellMeasure createURMShellDenVelMeasure(ItemMeta meta,
  73. [IMeasureItem? parent]) {
  74. URMShellMeasure measureShellDenVel = URMShellMeasure(meta, parent);
  75. measureShellDenVel.calculator = URMShellDenVelMeasureCal(
  76. measureShellDenVel,
  77. );
  78. return measureShellDenVel;
  79. }
  80. @override
  81. bool onExecuteMouse(PointInfo args) {
  82. if (waitingResult) return false;
  83. if (state == ItemStates.finished) {
  84. if (args.pointType == PointInfoType.mouseDown) {
  85. state = ItemStates.waiting;
  86. }
  87. }
  88. if (state == ItemStates.waiting) {
  89. if (args.pointType == PointInfoType.mouseDown) {
  90. handleMouseDownWhileWaiting(args);
  91. }
  92. } else if (state == ItemStates.running) {
  93. if (args.pointType == PointInfoType.mouseUp) return false;
  94. feature?.adopt(args);
  95. if (args.pointType == PointInfoType.mouseDown) {
  96. handleFinish();
  97. } else {
  98. checkAutoSnap(args);
  99. }
  100. }
  101. return true;
  102. }
  103. @override
  104. void handleMouseDownWhileWaiting(PointInfo args) {
  105. if (meta.measureType == MeasureTypes.URMShellPerfusionMeasure) {
  106. feature = ShellPerfusionImageFeature(this);
  107. } else {
  108. feature = ShellImageFeature(this);
  109. // if (args.hostVisualArea != null) {
  110. // feature!.hostVisualArea = args.hostVisualArea;
  111. // }
  112. // final point = args.toAreaLogicPoint();
  113. // feature!.adopt(point);
  114. }
  115. state = ItemStates.running;
  116. }
  117. bool waitingResult = false;
  118. void handleFinish({bool recordSharp = true}) async {
  119. if (recordSharp) {
  120. _recordSharp();
  121. }
  122. feature!.isActive = false;
  123. waitingResult = true;
  124. await doCalculateAsync();
  125. doFeatureFinish();
  126. doFeatureUpdate(); // 若不执行,子测量将无法自动切换
  127. PromptBox.dismiss();
  128. waitingResult = false;
  129. }
  130. void _recordSharp() {
  131. UrmSharpCopyBoard.recordSharp(
  132. UrmSharpCopyDataType.rim,
  133. feature!.innerPoints,
  134. );
  135. }
  136. /// 自动结束检测
  137. @override
  138. bool checkAutoSnap(PointInfo current, [bool autoFinishFeature = true]) {
  139. if (feature == null || feature!.innerPoints.length < 3) {
  140. isSmartMove = false;
  141. return _syncState(false);
  142. }
  143. // final viewport = feature!.hostVisualArea!.viewport!;
  144. if (isAutoSnap == false) return false;
  145. final pixelSize = application.displaySize;
  146. final p1 = feature!.innerPoints.first.scale2Size(pixelSize);
  147. final p2 = current.scale2Size(pixelSize);
  148. final length = (p1 - p2).length;
  149. if (length > snapThreshold * 2.0 && !isSmartMove) {
  150. isSmartMove = true;
  151. }
  152. if (length < snapThreshold && isSmartMove) {
  153. feature!.innerPoints.last = feature!.innerPoints.first.clone();
  154. /// 此处的最后一个点,方便计算,但是绘制时要剔除
  155. // feature!.innerPoints.removeLast();
  156. HapticFeedback.heavyImpact();
  157. if (autoFinishFeature) {
  158. handleFinish();
  159. }
  160. isSmartMove = false;
  161. return _syncState(true);
  162. } else {
  163. return _syncState(false);
  164. }
  165. }
  166. bool _syncState(bool isSnap) {
  167. snapState = isSnap;
  168. return snapState;
  169. }
  170. }
  171. class ShellImageFeature extends TraceFeature {
  172. ShellImageFeature(AreaItemAbstract refItem) : super(refItem);
  173. List<DPoint> outerExterPoints = [];
  174. List<DPoint> interExterPoints = [];
  175. bool isNeedPaintColors = false;
  176. /// 绘制rim 外环
  177. @override
  178. void paint(Canvas canvas, Size size) {
  179. super.paint(canvas, size);
  180. if (outerExterPoints.isEmpty) {
  181. return;
  182. }
  183. final pixelPoints = outerExterPoints.map((e) {
  184. return convert2ViewPoint(size, e).toOffset();
  185. }).toList();
  186. canvas.drawDashPointsLine(pixelPoints, 1, 10, paintLinePan, close: true);
  187. if (isNeedPaintColors) {
  188. final inPixelPoints = interExterPoints
  189. .map((e) => convert2ViewPoint(size, e).toOffset())
  190. .toList();
  191. // 创建一个蓝色带透明度的Paint对象,用于填充区域
  192. Paint outPaint = Paint()
  193. ..color = const Color(0xFF2897ea).withOpacity(0.5)
  194. ..style = PaintingStyle.fill;
  195. // 创建一个蓝色带透明度的Paint对象,用于填充区域
  196. Paint innerPaint = Paint()
  197. ..color = const Color(0xFF57ED26).withOpacity(0.5)
  198. ..style = PaintingStyle.fill;
  199. // 创建Path并连接点
  200. Path path = Path();
  201. Path pathb = Path();
  202. if (pixelPoints.isNotEmpty) {
  203. path.moveTo(pixelPoints[0].dx, pixelPoints[0].dy);
  204. for (var point in pixelPoints) {
  205. path.lineTo(point.dx, point.dy);
  206. }
  207. path.close(); // 闭合路径
  208. }
  209. if (inPixelPoints.isNotEmpty) {
  210. pathb.moveTo(inPixelPoints[0].dx, inPixelPoints[0].dy);
  211. for (var point in inPixelPoints) {
  212. pathb.lineTo(point.dx, point.dy);
  213. }
  214. pathb.close(); // 闭合路径
  215. }
  216. // 绘制路径
  217. canvas.drawPath(path, outPaint);
  218. // 绘制路径
  219. canvas.drawPath(pathb, innerPaint);
  220. }
  221. }
  222. }
  223. class ShellPerfusionImageFeature extends TraceFeature {
  224. ShellPerfusionImageFeature(AreaItemAbstract refItem) : super(refItem);
  225. ui.Image? perfusionImg;
  226. DPoint? leftTopPoint;
  227. DPoint? rightBottomPoint;
  228. List<DPoint> outerExterPoints = [];
  229. /// 绘制灌注图
  230. @override
  231. void paintPerfusion(Canvas canvas, Size size) {
  232. if (perfusionImg != null) {
  233. Paint paint = Paint();
  234. Rect src = Rect.fromLTWH(
  235. 0,
  236. 0,
  237. perfusionImg!.width.toDouble(),
  238. perfusionImg!.height.toDouble(),
  239. );
  240. if (leftTopPoint == null || rightBottomPoint == null) {
  241. return;
  242. }
  243. DPoint leftTop = convert2ViewPoint(size, leftTopPoint!);
  244. DPoint rightBottom = convert2ViewPoint(size, rightBottomPoint!);
  245. convert2ViewPoint(size, rightBottomPoint!);
  246. Rect dst = Rect.fromPoints(
  247. Offset(leftTop.x, leftTop.y), Offset(rightBottom.x, rightBottom.y));
  248. canvas.drawImageRect(perfusionImg!, src, dst, paint);
  249. final pixelPoints = outerExterPoints.map((e) {
  250. return convert2ViewPoint(size, e).toOffset();
  251. }).toList();
  252. canvas.drawDashPointsLine(pixelPoints, 1, 10, paintLinePan, close: true);
  253. }
  254. }
  255. }