straightline.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. import 'dart: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/time_motion.dart';
  9. import 'package:fis_measure/process/items/item.dart';
  10. import 'package:fis_measure/utils/canvas.dart';
  11. import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
  12. import 'package:fis_measure/view/gesture/positioned_cursor.dart';
  13. import 'package:fis_measure/view/gesture/positioned_touch_cursor.dart';
  14. import 'package:fis_ui/index.dart';
  15. import 'package:flutter/foundation.dart';
  16. import 'package:get/get.dart';
  17. import 'package:vid/us/vid_us_mode.dart';
  18. import '../calcuators/distance.dart';
  19. import '../items/item_feature.dart';
  20. /// 直线
  21. class StraightLine extends MeasureItem<StraightLineFeature> {
  22. late final touchState = Get.find<ITouchPointState>();
  23. late final mouseState = Get.find<IMouseState>();
  24. StraightLine(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
  25. static StraightLine createDistance(ItemMeta meta, [IMeasureItem? parent]) {
  26. StraightLine sraightLine = StraightLine(meta, parent);
  27. sraightLine.calculator = DistanceCal(sraightLine);
  28. return sraightLine;
  29. }
  30. static StraightLine createSlope(ItemMeta meta, [IMeasureItem? parent]) {
  31. StraightLine sraightLine = StraightLine(meta, parent);
  32. sraightLine.calculator = SlopeCal(sraightLine);
  33. return sraightLine;
  34. }
  35. static StraightLine createSlopeDoppler(ItemMeta meta,
  36. [IMeasureItem? parent]) {
  37. StraightLine sraightLine = StraightLine(meta, parent);
  38. sraightLine.calculator = SlopeDopplerCal(sraightLine);
  39. return sraightLine;
  40. }
  41. static StraightLine createVerticalDistance(ItemMeta meta,
  42. [IMeasureItem? parent]) {
  43. StraightLine sraightLine = StraightLine(meta, parent);
  44. sraightLine.calculator = VerticalDistanceCal(sraightLine);
  45. return sraightLine;
  46. }
  47. static StraightLine createTimeSpan(ItemMeta meta, [IMeasureItem? parent]) {
  48. StraightLine sraightLine = StraightLine(meta, parent);
  49. sraightLine.calculator = TimeSpanCal(sraightLine);
  50. return sraightLine;
  51. }
  52. @override
  53. bool onExecuteMouse(PointInfo args) {
  54. if (state == ItemStates.finished) {
  55. if (args.pointType == PointInfoType.mouseDown) {
  56. state = ItemStates.waiting;
  57. } else {
  58. return false;
  59. }
  60. }
  61. if (state == ItemStates.waiting) {
  62. if (args.pointType == PointInfoType.mouseDown) {
  63. handleMouseDownWhileWaiting(args);
  64. }
  65. } else if (state == ItemStates.running) {
  66. if (args.pointType == PointInfoType.mouseUp) return false;
  67. feature?.endPoint = args;
  68. doCalculate();
  69. if (args.pointType == PointInfoType.mouseDown) {
  70. doFeatureFinish();
  71. ///重置十字样式
  72. changeCrossIndicatorStyle(CrossIndicatorStyle.nomal);
  73. }
  74. }
  75. return true;
  76. }
  77. PointInfo? firstTouchStartPoint;
  78. bool isFirstPointMove = false;
  79. DPoint? secondTouchStartPoint;
  80. bool isSecondPointMove = false;
  81. @override
  82. bool onExecuteTouch(PointInfo args) {
  83. if (state == ItemStates.finished) {
  84. if (args.pointType == PointInfoType.touchDown) {
  85. isFirstPointMove = false;
  86. isSecondPointMove = false;
  87. state = ItemStates.waiting;
  88. }
  89. }
  90. if (state == ItemStates.waiting) {
  91. switch (args.pointType) {
  92. case PointInfoType.touchDown:
  93. firstTouchStartPoint = args; // 设置线段起点
  94. handleTouchBeforeStart(firstTouchStartPoint!); // 开始绘制前动态设置第一个起点
  95. break;
  96. case PointInfoType.touchMove:
  97. isFirstPointMove = true;
  98. args.addOffset(0, -0.2); // 添加偏移
  99. feature?.startPoint = args;
  100. feature?.endPoint = args;
  101. break;
  102. case PointInfoType.touchUp:
  103. if (isFirstPointMove) {
  104. args.addOffset(0, -0.2); // 添加偏移
  105. }
  106. firstTouchStartPoint = args; // 设置线段起点
  107. feature?.startPoint = args;
  108. state = ItemStates.running;
  109. break;
  110. default:
  111. break;
  112. }
  113. } else if (state == ItemStates.running) {
  114. switch (args.pointType) {
  115. case PointInfoType.touchDown:
  116. secondTouchStartPoint = args;
  117. break;
  118. case PointInfoType.touchMove:
  119. isSecondPointMove = true;
  120. doCalculate();
  121. feature?.endPoint = firstTouchStartPoint!
  122. .clone()
  123. .addVector(args - secondTouchStartPoint!);
  124. break;
  125. case PointInfoType.touchUp:
  126. if (!isSecondPointMove) {
  127. feature?.endPoint = args;
  128. doCalculate();
  129. }
  130. doFeatureFinish();
  131. break;
  132. default:
  133. break;
  134. }
  135. }
  136. return true;
  137. }
  138. void handleMouseDownWhileWaiting(PointInfo args) {
  139. // TODO: 判断是否当前area
  140. // 转换为Area逻辑位置
  141. final point = args.toAreaLogicPoint();
  142. // feature = StraightLineFeature(this, point, point);
  143. if (args.hostVisualArea != null) {
  144. handleTissueTM(args.hostVisualArea!.mode.modeType, point);
  145. feature!.hostVisualArea = args.hostVisualArea;
  146. }
  147. state = ItemStates.running;
  148. }
  149. void handleTouchBeforeStart(PointInfo args) {
  150. // 转换为Area逻辑位置
  151. final point = args.toAreaLogicPoint();
  152. // feature = StraightLineFeature(this, point, point);
  153. if (args.hostVisualArea != null) {
  154. handleTissueTM(args.hostVisualArea!.mode.modeType, point);
  155. feature!.hostVisualArea = args.hostVisualArea;
  156. }
  157. }
  158. /// 处理TissueTimeMotion模式
  159. void handleTissueTM(VidUsModeType mode, DPoint point) {
  160. if (mode == VidUsModeType.TissueTM || mode == VidUsModeType.Doppler) {
  161. switch (meta.measureType) {
  162. case MeasureTypes.TimeSpan:
  163. feature = StraightLineTimeMotionFeature(this, point, point,
  164. ifHorizontal: false);
  165. changeCrossIndicatorStyle(CrossIndicatorStyle.vertical);
  166. break;
  167. case MeasureTypes.VerticalDistance:
  168. feature = StraightLineTimeMotionFeature(this, point, point);
  169. changeCrossIndicatorStyle(CrossIndicatorStyle.horizontal);
  170. break;
  171. case MeasureTypes.Slope:
  172. feature = StraightLineSlopeFeature(this, point, point);
  173. break;
  174. case MeasureTypes.SlopeDoppler:
  175. feature = StraightLineSlopeFeature(this, point, point);
  176. break;
  177. case MeasureTypes.Pht:
  178. feature = StraightLinePhtFeature(this, point, point);
  179. changeCrossIndicatorStyle(CrossIndicatorStyle.vertical);
  180. break;
  181. default:
  182. }
  183. } else {
  184. feature = StraightLineFeature(this, point, point);
  185. }
  186. }
  187. void changeCrossIndicatorStyle(CrossIndicatorStyle e) {
  188. if (kIsMobile) {
  189. touchState.crossIndicatorStyleChanged.emit(this, e);
  190. } else {
  191. mouseState.crossIndicatorStyleChanged.emit(this, e);
  192. }
  193. }
  194. }
  195. class StraightLineFeature extends MeasureItemFeature {
  196. StraightLineFeature(
  197. IMeasureItem refItem,
  198. DPoint startPoint,
  199. DPoint endPoint,
  200. ) : super(refItem) {
  201. innerPoints.add(startPoint);
  202. innerPoints.add(endPoint);
  203. }
  204. /// 起点
  205. DPoint get startPoint => innerPoints[0];
  206. set startPoint(DPoint value) => innerPoints[0] = value;
  207. /// 终点
  208. DPoint get endPoint => innerPoints[1];
  209. set endPoint(DPoint value) => innerPoints[1] = value;
  210. /// 长度
  211. double get length => (endPoint - startPoint).length;
  212. @override
  213. void paint(Canvas canvas, Size size) {
  214. if (startPoint == endPoint && kIsWeb) return;
  215. drawId(canvas, size, idText);
  216. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  217. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  218. final distanceOffset = endOffset - startOffset;
  219. if (distanceOffset.distance < measureData.getMinCursorDistance()) {
  220. drawMiniVertex(canvas, startOffset);
  221. drawMiniVertex(canvas, endOffset, isActive);
  222. } else {
  223. drawVertex(canvas, startOffset);
  224. drawVertex(canvas, endOffset, isActive);
  225. }
  226. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  227. }
  228. }
  229. class StraightLineTimeMotionFeature extends StraightLineFeature {
  230. StraightLineTimeMotionFeature(
  231. IMeasureItem refItem, DPoint startPoint, DPoint endPoint,
  232. {this.ifHorizontal = true})
  233. : super(refItem, startPoint, endPoint);
  234. final bool ifHorizontal;
  235. @override
  236. void paint(Canvas canvas, Size size) {
  237. if (startPoint == endPoint && kIsWeb) return;
  238. drawId(canvas, size, idText);
  239. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  240. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  241. if (ifHorizontal) {
  242. drawMark(canvas, startOffset);
  243. drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
  244. } else {
  245. drawMark(canvas, startOffset, false, ifHorizontal);
  246. drawMark(
  247. canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
  248. }
  249. }
  250. }
  251. class StraightLineSlopeFeature extends StraightLineFeature {
  252. StraightLineSlopeFeature(
  253. IMeasureItem refItem, DPoint startPoint, DPoint endPoint)
  254. : super(refItem, startPoint, endPoint);
  255. @override
  256. void paint(Canvas canvas, Size size) {
  257. if (startPoint == endPoint && kIsWeb) return;
  258. drawId(canvas, size, idText);
  259. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  260. drawVertex(canvas, startOffset);
  261. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  262. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  263. drawVertex(canvas, endOffset, isActive);
  264. }
  265. }
  266. class StraightLinePhtFeature extends StraightLineFeature {
  267. StraightLinePhtFeature(
  268. IMeasureItem refItem, DPoint startPoint, DPoint endPoint)
  269. : super(refItem, startPoint, endPoint);
  270. DPoint get regionCenter => hostVisualArea!.displayRegion.center;
  271. @override
  272. void paint(Canvas canvas, Size size) {
  273. if (startPoint == endPoint && kIsWeb) return;
  274. drawId(canvas, size, idText);
  275. final distanceToCenter = (startPoint.y - regionCenter.y);
  276. //TODO:[Gavin] 偏移量比例系数待精确
  277. final endPointY = startPoint.y - distanceToCenter / 4;
  278. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  279. final endOffset =
  280. convert2ViewPoint(size, DPoint(endPoint.x, endPointY)).toOffset();
  281. drawVertex(canvas, startOffset, false);
  282. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  283. drawVertex(canvas, endOffset, isActive);
  284. }
  285. }