straightline.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. if (isMoveTargetOutOfRange(args)) return true;
  100. feature?.startPoint = args;
  101. feature?.endPoint = args;
  102. break;
  103. case PointInfoType.touchUp:
  104. if (isFirstPointMove) {
  105. args.addOffset(0, -0.2); // 添加偏移
  106. }
  107. firstTouchStartPoint = args; // 设置线段起点
  108. feature?.startPoint = args;
  109. state = ItemStates.running;
  110. break;
  111. default:
  112. break;
  113. }
  114. } else if (state == ItemStates.running) {
  115. switch (args.pointType) {
  116. case PointInfoType.touchDown:
  117. secondTouchStartPoint = args;
  118. break;
  119. case PointInfoType.touchMove:
  120. PointInfo newPoint = PointInfo.fromOffset(
  121. firstTouchStartPoint!
  122. .clone()
  123. .addVector(args - secondTouchStartPoint!)
  124. .toOffset(),
  125. args.pointType);
  126. newPoint.hostVisualArea = args.hostVisualArea;
  127. if (isMoveTargetOutOfRange(newPoint)) return true;
  128. isSecondPointMove = true;
  129. doCalculate();
  130. feature?.endPoint = newPoint;
  131. break;
  132. case PointInfoType.touchUp:
  133. if (!isSecondPointMove) {
  134. feature?.endPoint = args;
  135. doCalculate();
  136. }
  137. doFeatureFinish();
  138. break;
  139. default:
  140. break;
  141. }
  142. }
  143. return true;
  144. }
  145. void handleMouseDownWhileWaiting(PointInfo args) {
  146. // TODO: 判断是否当前area
  147. // 转换为Area逻辑位置
  148. final point = args.toAreaLogicPoint();
  149. // feature = StraightLineFeature(this, point, point);
  150. if (args.hostVisualArea != null) {
  151. handleTissueTM(args.hostVisualArea!.mode.modeType, point);
  152. feature!.hostVisualArea = args.hostVisualArea;
  153. }
  154. state = ItemStates.running;
  155. }
  156. void handleTouchBeforeStart(PointInfo args) {
  157. // 转换为Area逻辑位置
  158. final point = args.toAreaLogicPoint();
  159. // feature = StraightLineFeature(this, point, point);
  160. if (args.hostVisualArea != null) {
  161. handleTissueTM(args.hostVisualArea!.mode.modeType, point);
  162. feature!.hostVisualArea = args.hostVisualArea;
  163. }
  164. }
  165. /// 处理TissueTimeMotion模式
  166. void handleTissueTM(VidUsModeType mode, DPoint point) {
  167. if (mode == VidUsModeType.TissueTM || mode == VidUsModeType.Doppler) {
  168. switch (meta.measureType) {
  169. case MeasureTypes.TimeSpan:
  170. feature = StraightLineTimeMotionFeature(this, point, point,
  171. ifHorizontal: false);
  172. changeCrossIndicatorStyle(CrossIndicatorStyle.vertical);
  173. break;
  174. case MeasureTypes.VerticalDistance:
  175. feature = StraightLineTimeMotionFeature(this, point, point);
  176. changeCrossIndicatorStyle(CrossIndicatorStyle.horizontal);
  177. break;
  178. case MeasureTypes.Slope:
  179. feature = StraightLineSlopeFeature(this, point, point);
  180. break;
  181. case MeasureTypes.SlopeDoppler:
  182. feature = StraightLineSlopeFeature(this, point, point);
  183. break;
  184. case MeasureTypes.Pht:
  185. feature = StraightLinePhtFeature(this, point, point);
  186. changeCrossIndicatorStyle(CrossIndicatorStyle.vertical);
  187. break;
  188. default:
  189. }
  190. } else {
  191. feature = StraightLineFeature(this, point, point);
  192. }
  193. }
  194. void changeCrossIndicatorStyle(CrossIndicatorStyle e) {
  195. if (kIsMobile) {
  196. touchState.crossIndicatorStyleChanged.emit(this, e);
  197. } else {
  198. mouseState.crossIndicatorStyleChanged.emit(this, e);
  199. }
  200. }
  201. }
  202. class StraightLineFeature extends MeasureItemFeature {
  203. StraightLineFeature(
  204. IMeasureItem refItem,
  205. DPoint startPoint,
  206. DPoint endPoint,
  207. ) : super(refItem) {
  208. innerPoints.add(startPoint);
  209. innerPoints.add(endPoint);
  210. }
  211. /// 起点
  212. DPoint get startPoint => innerPoints[0];
  213. set startPoint(DPoint value) => innerPoints[0] = value;
  214. /// 终点
  215. DPoint get endPoint => innerPoints[1];
  216. set endPoint(DPoint value) => innerPoints[1] = value;
  217. /// 长度
  218. double get length => (endPoint - startPoint).length;
  219. @override
  220. void paint(Canvas canvas, Size size) {
  221. if (startPoint == endPoint && kIsWeb) return;
  222. drawId(canvas, size, idText);
  223. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  224. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  225. final distanceOffset = endOffset - startOffset;
  226. if (distanceOffset.distance < measureData.getMinCursorDistance()) {
  227. drawMiniVertex(canvas, startOffset);
  228. drawMiniVertex(canvas, endOffset, isActive);
  229. } else {
  230. drawVertex(canvas, startOffset);
  231. drawVertex(canvas, endOffset, isActive);
  232. }
  233. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  234. }
  235. }
  236. class StraightLineTimeMotionFeature extends StraightLineFeature {
  237. StraightLineTimeMotionFeature(
  238. IMeasureItem refItem, DPoint startPoint, DPoint endPoint,
  239. {this.ifHorizontal = true})
  240. : super(refItem, startPoint, endPoint);
  241. final bool ifHorizontal;
  242. @override
  243. void paint(Canvas canvas, Size size) {
  244. if (startPoint == endPoint && kIsWeb) return;
  245. drawId(canvas, size, idText);
  246. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  247. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  248. if (ifHorizontal) {
  249. drawMark(canvas, startOffset);
  250. drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
  251. } else {
  252. drawMark(canvas, startOffset, false, ifHorizontal);
  253. drawMark(
  254. canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
  255. }
  256. }
  257. }
  258. class StraightLineSlopeFeature extends StraightLineFeature {
  259. StraightLineSlopeFeature(
  260. IMeasureItem refItem, DPoint startPoint, DPoint endPoint)
  261. : super(refItem, startPoint, endPoint);
  262. @override
  263. void paint(Canvas canvas, Size size) {
  264. if (startPoint == endPoint && kIsWeb) return;
  265. drawId(canvas, size, idText);
  266. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  267. drawVertex(canvas, startOffset);
  268. final endOffset = convert2ViewPoint(size, endPoint).toOffset();
  269. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  270. drawVertex(canvas, endOffset, isActive);
  271. }
  272. }
  273. class StraightLinePhtFeature extends StraightLineFeature {
  274. StraightLinePhtFeature(
  275. IMeasureItem refItem, DPoint startPoint, DPoint endPoint)
  276. : super(refItem, startPoint, endPoint);
  277. DPoint get regionCenter => hostVisualArea!.displayRegion.center;
  278. @override
  279. void paint(Canvas canvas, Size size) {
  280. if (startPoint == endPoint && kIsWeb) return;
  281. drawId(canvas, size, idText);
  282. final distanceToCenter = (startPoint.y - regionCenter.y);
  283. //TODO:[Gavin] 偏移量比例系数待精确
  284. final endPointY = startPoint.y - distanceToCenter / 4;
  285. final startOffset = convert2ViewPoint(size, startPoint).toOffset();
  286. final endOffset =
  287. convert2ViewPoint(size, DPoint(endPoint.x, endPointY)).toOffset();
  288. drawVertex(canvas, startOffset, false);
  289. canvas.drawDashLine(startOffset, endOffset, 1, 10, paintLinePan);
  290. drawVertex(canvas, endOffset, isActive);
  291. }
  292. }