ray.dart 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. if (isMoveTargetOutOfRange(args)) return true;
  86. feature?.point = args;
  87. } else {
  88. PointInfo newPoint = PointInfo.fromOffset(
  89. lastLinePosition
  90. .clone()
  91. .addVector(args - touchStartPoint)
  92. .toOffset(),
  93. args.pointType);
  94. newPoint.hostVisualArea = args.hostVisualArea;
  95. if (isMoveTargetOutOfRange(newPoint)) return true;
  96. feature?.point = newPoint;
  97. }
  98. doCalculate();
  99. }
  100. if (args.pointType == PointInfoType.touchUp && isNeedFinish) {
  101. doFeatureFinish();
  102. }
  103. }
  104. return true;
  105. }
  106. static Ray createRay(ItemMeta meta, [IMeasureItem? parent]) {
  107. final ray = Ray(meta, parent);
  108. ray.calculator = RayDepthCal(ray);
  109. return ray;
  110. }
  111. void _updateInitializeAngle() {
  112. int switchNumber = switchInitialAngle ? -1 : 1;
  113. _initializeAngle = _initializeAngleVal * switchNumber;
  114. }
  115. }
  116. class RayFeature extends MeasureItemFeature {
  117. double _angle = 0;
  118. bool _isReverse = false;
  119. RayFeature(Ray refItem, DPoint point) : super(refItem) {
  120. innerPoints.add(point.clone());
  121. angle = refItem.initializeAngle;
  122. }
  123. DPoint get point => innerPoints[0];
  124. set point(DPoint value) {
  125. innerPoints[0] = value;
  126. }
  127. double get angle => _angle;
  128. set angle(double value) {
  129. if (value != _angle) {
  130. _angle = value;
  131. }
  132. }
  133. bool get isReverse => _isReverse;
  134. set isReverse(bool value) {
  135. if (value != _isReverse) {
  136. _isReverse = value;
  137. }
  138. }
  139. RectRegion get viewRegion => hostVisualArea!.viewport!.area.layoutRegion!;
  140. @override
  141. void paint(Canvas canvas, Size size) {
  142. if (innerPoints.isEmpty) return;
  143. final curItemName = refItem.displayName;
  144. final offset = convert2ViewPoint(size, point).toOffset();
  145. final rect = Rect.fromLTWH(
  146. viewRegion.left * size.width,
  147. viewRegion.top * size.height,
  148. viewRegion.width * size.width,
  149. viewRegion.height * size.height);
  150. List<Offset> twoPoint = [const Offset(0, 0), const Offset(0, 0)];
  151. final idText = '$id.${refItem.displayName}';
  152. switch (curItemName) {
  153. case "Baseline":
  154. twoPoint = calcLinePoint(rect, offset, 0);
  155. drawCustomId(canvas, size, twoPoint[1], idText);
  156. break;
  157. case "Line α":
  158. twoPoint = calcLinePoint(rect, offset, angle);
  159. drawCustomId(canvas, size, twoPoint[1], idText);
  160. break;
  161. case "Line β":
  162. twoPoint = calcLinePoint(rect, offset, 180 - angle);
  163. drawCustomId(canvas, size, twoPoint[0], idText);
  164. break;
  165. default:
  166. break;
  167. }
  168. canvas.drawDashLine(twoPoint[0], twoPoint[1], 1, 10, paintLinePan);
  169. }
  170. List<Offset> calcLinePoint(Rect rect, Offset innerPoint, double angle) {
  171. List<Offset> twoPoint = [const Offset(0, 0), const Offset(0, 0)];
  172. if (!rect.contains(innerPoint)) return twoPoint;
  173. final tan = math.tan(angle * math.pi / 180);
  174. final x = innerPoint.dx;
  175. final y = innerPoint.dy;
  176. final d1 = x - y / tan;
  177. twoPoint[0] = Offset(d1, 0);
  178. final d2 = (rect.height - y) / tan + x;
  179. twoPoint[1] = Offset(d2, rect.height);
  180. if (angle <= 90) {
  181. if (d1 < rect.left) {
  182. twoPoint[0] = Offset(rect.left, y - tan * (x - rect.left));
  183. }
  184. if (d2 > rect.right) {
  185. twoPoint[1] = Offset(rect.right, y + tan * (rect.right - x));
  186. }
  187. } else {
  188. if (d1 > rect.right) {
  189. twoPoint[0] = Offset(rect.right, y - tan * (x - rect.right));
  190. }
  191. if (d2 < rect.left) {
  192. twoPoint[1] = Offset(rect.left, y + tan * (rect.left - x));
  193. }
  194. }
  195. return twoPoint;
  196. }
  197. }