ray.dart 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import 'dart:ui';
  2. import 'dart:math' as math;
  3. import 'package:fis_measure/interfaces/date_types/point.dart';
  4. import 'package:fis_measure/interfaces/date_types/rect_region.dart';
  5. import 'package:fis_measure/interfaces/enums/items.dart';
  6. import 'package:fis_measure/interfaces/process/items/item.dart';
  7. import 'package:fis_measure/interfaces/process/items/item_metas.dart';
  8. import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
  9. import 'package:fis_measure/process/calcuators/ray.dart';
  10. import 'package:fis_measure/process/items/item.dart';
  11. import 'package:fis_measure/process/items/item_feature.dart';
  12. import 'package:fis_measure/utils/canvas.dart';
  13. class Ray extends MeasureItem<RayFeature> {
  14. double _initializeAngle = 0;
  15. double _initializeAngleVal = 0;
  16. bool _switchInitialAngle = false;
  17. Ray(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
  18. double get initializeAngle => _initializeAngle;
  19. set initializeAngle(double value) {
  20. if (value != _initializeAngle) {
  21. _initializeAngleVal = value;
  22. _updateInitializeAngle();
  23. }
  24. }
  25. bool get switchInitialAngle => _switchInitialAngle;
  26. set switchInitialAngle(bool value) {
  27. if (value != _switchInitialAngle) {
  28. _switchInitialAngle = value;
  29. _updateInitializeAngle();
  30. }
  31. }
  32. @override
  33. bool onExecuteMouse(PointInfo args) {
  34. if (state == ItemStates.finished || state == ItemStates.waiting) {
  35. if (args.pointType == PointInfoType.mouseMove) {
  36. feature = RayFeature(this, args);
  37. feature!.hostVisualArea = args.hostVisualArea;
  38. final viewport = args.hostVisualArea!.viewport!;
  39. feature!.isReverse =
  40. viewport.isFlipHorizontal ^ viewport.isFlipVertical;
  41. state = ItemStates.running;
  42. }
  43. }
  44. if (state == ItemStates.running) {
  45. if (args.pointType == PointInfoType.mouseUp) return false;
  46. feature?.point = args;
  47. doCalculate();
  48. if (args.pointType == PointInfoType.mouseDown) {
  49. doFeatureFinish();
  50. }
  51. }
  52. return true;
  53. }
  54. // 是否需要结束当前的测量过程,用于移动端的交互
  55. bool isNeedFinish = true;
  56. bool isFirstTouch = true;
  57. DPoint touchStartPoint = DPoint(0, 0);
  58. DPoint lastLinePosition = DPoint(0, 0);
  59. @override
  60. bool onExecuteTouch(PointInfo args) {
  61. if (state == ItemStates.waiting || state == ItemStates.finished) {
  62. if (args.pointType == PointInfoType.touchMove) {
  63. if (measuredFeatures.isEmpty) {
  64. feature = RayFeature(this, args);
  65. feature!.hostVisualArea = args.hostVisualArea;
  66. final viewport = args.hostVisualArea!.viewport!;
  67. feature!.isReverse =
  68. viewport.isFlipHorizontal ^ viewport.isFlipVertical;
  69. } else {
  70. feature = measuredFeatures.first;
  71. }
  72. state = ItemStates.running;
  73. }
  74. }
  75. if (state == ItemStates.running) {
  76. if (args.pointType == PointInfoType.touchDown) {
  77. touchStartPoint = args;
  78. lastLinePosition = feature?.point ?? args;
  79. isNeedFinish = true;
  80. isFirstTouch = feature?.point == null;
  81. }
  82. if (args.pointType == PointInfoType.touchMove) {
  83. isNeedFinish = false;
  84. if (isFirstTouch) {
  85. feature?.point = args;
  86. } else {
  87. feature?.point =
  88. lastLinePosition.clone().addVector(args - touchStartPoint);
  89. }
  90. doCalculate();
  91. }
  92. if (args.pointType == PointInfoType.touchUp && isNeedFinish) {
  93. doFeatureFinish();
  94. }
  95. }
  96. return true;
  97. }
  98. static Ray createRay(ItemMeta meta, [IMeasureItem? parent]) {
  99. final ray = Ray(meta, parent);
  100. ray.calculator = RayDepthCal(ray);
  101. return ray;
  102. }
  103. void _updateInitializeAngle() {
  104. int switchNumber = switchInitialAngle ? -1 : 1;
  105. _initializeAngle = _initializeAngleVal * switchNumber;
  106. }
  107. }
  108. class RayFeature extends MeasureItemFeature {
  109. double _angle = 0;
  110. bool _isReverse = false;
  111. RayFeature(Ray refItem, DPoint point) : super(refItem) {
  112. innerPoints.add(point.clone());
  113. angle = refItem.initializeAngle;
  114. }
  115. DPoint get point => innerPoints[0];
  116. set point(DPoint value) {
  117. innerPoints[0] = value;
  118. }
  119. double get angle => _angle;
  120. set angle(double value) {
  121. if (value != _angle) {
  122. _angle = value;
  123. }
  124. }
  125. bool get isReverse => _isReverse;
  126. set isReverse(bool value) {
  127. if (value != _isReverse) {
  128. _isReverse = value;
  129. }
  130. }
  131. RectRegion get viewRegion => hostVisualArea!.viewport!.area.layoutRegion!;
  132. @override
  133. void paint(Canvas canvas, Size size) {
  134. if (innerPoints.isEmpty) return;
  135. final curItemName = refItem.displayName;
  136. final offset = convert2ViewPoint(size, point).toOffset();
  137. final rect = Rect.fromLTWH(
  138. viewRegion.left * size.width,
  139. viewRegion.top * size.height,
  140. viewRegion.width * size.width,
  141. viewRegion.height * size.height);
  142. List<Offset> twoPoint = [const Offset(0, 0), const Offset(0, 0)];
  143. final idText = '$id.${refItem.displayName}';
  144. switch (curItemName) {
  145. case "Baseline":
  146. twoPoint = calcLinePoint(rect, offset, 0);
  147. drawCustomId(canvas, size, twoPoint[1], idText);
  148. break;
  149. case "Line α":
  150. twoPoint = calcLinePoint(rect, offset, angle);
  151. drawCustomId(canvas, size, twoPoint[1], idText);
  152. break;
  153. case "Line β":
  154. twoPoint = calcLinePoint(rect, offset, 180 - angle);
  155. drawCustomId(canvas, size, twoPoint[0], idText);
  156. break;
  157. default:
  158. break;
  159. }
  160. canvas.drawDashLine(twoPoint[0], twoPoint[1], 1, 10, paintLinePan);
  161. }
  162. List<Offset> calcLinePoint(Rect rect, Offset innerPoint, double angle) {
  163. List<Offset> twoPoint = [const Offset(0, 0), const Offset(0, 0)];
  164. if (!rect.contains(innerPoint)) return twoPoint;
  165. final tan = math.tan(angle * math.pi / 180);
  166. final x = innerPoint.dx;
  167. final y = innerPoint.dy;
  168. final d1 = x - y / tan;
  169. twoPoint[0] = Offset(d1, 0);
  170. final d2 = (rect.height - y) / tan + x;
  171. twoPoint[1] = Offset(d2, rect.height);
  172. if (angle <= 90) {
  173. if (d1 < rect.left) {
  174. twoPoint[0] = Offset(rect.left, y - tan * (x - rect.left));
  175. }
  176. if (d2 > rect.right) {
  177. twoPoint[1] = Offset(rect.right, y + tan * (rect.right - x));
  178. }
  179. } else {
  180. if (d1 > rect.right) {
  181. twoPoint[0] = Offset(rect.right, y - tan * (x - rect.right));
  182. }
  183. if (d2 < rect.left) {
  184. twoPoint[1] = Offset(rect.left, y + tan * (rect.left - x));
  185. }
  186. }
  187. return twoPoint;
  188. }
  189. }