item_feature.dart 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import 'package:fis_common/logger/logger.dart';
  2. import 'package:fis_measure/interfaces/date_types/point.dart';
  3. import 'package:fis_measure/interfaces/process/calculators/values.dart';
  4. import 'package:fis_measure/interfaces/process/items/item.dart';
  5. import 'package:fis_measure/interfaces/process/items/item_feature.dart';
  6. import 'package:fis_measure/interfaces/process/items/item_metas.dart';
  7. import 'package:fis_measure/interfaces/process/visuals/visual_area.dart';
  8. import 'package:fis_measure/process/workspace/measure_data_controller.dart';
  9. import 'package:fis_measure/utils/canvas.dart';
  10. import 'package:fis_measure/values/colors.dart';
  11. import 'package:flutter/widgets.dart';
  12. import 'package:get/get.dart';
  13. import 'package:vid/us/vid_us_unit.dart';
  14. import 'item.dart';
  15. abstract class MeasureItemFeature implements IMeasureItemFeature {
  16. late IMeasureItem _refItem;
  17. late List<DPoint> _innerPoints;
  18. late FeatureStyle _featureStyle;
  19. IVisualArea? _hostVisualArea;
  20. bool _isActive = true;
  21. int _id = 0;
  22. final List<ValueBase> _values = [];
  23. late final measureData = Get.find<MeasureDataController>();
  24. int _activeIndex = -1;
  25. @protected
  26. final paintPan = Paint()
  27. ..color = MeasureColors.Primary
  28. ..isAntiAlias = true
  29. ..strokeWidth = 2
  30. ..style = PaintingStyle.stroke;
  31. Paint get paintLinePan => measureData.paintLinePan;
  32. Paint get paintPointPan => measureData.paintPointPan;
  33. MeasureItemFeature(IMeasureItem refItem) {
  34. _refItem = refItem;
  35. if (refItem.parent != null) {
  36. _id = refItem.parent!.feature?.id ?? 0;
  37. } else {
  38. _id = refItem.assignId();
  39. }
  40. _innerPoints = [];
  41. _recordHistory();
  42. try {
  43. final measureData = Get.find<MeasureDataController>();
  44. _featureStyle = FeatureStyle(
  45. showDepthGuideline:
  46. measureData.measureSystemSetting.showDepthGuideline,
  47. showBriefAnnotation:
  48. measureData.measureSystemSetting.showBriefAnnotation);
  49. } catch (e) {
  50. logger.e("Init meature item's feature style failed: $e");
  51. }
  52. }
  53. int get activeIndex => _activeIndex;
  54. set activeIndex(int val) {
  55. if (val != _activeIndex) {
  56. _activeIndex = val;
  57. }
  58. }
  59. @override
  60. FeatureStyle get featureStyle => _featureStyle;
  61. @override
  62. List<DPoint> get innerPoints => _innerPoints;
  63. @override
  64. MeasureItem get refItem => _refItem as MeasureItem;
  65. /// 所在区域
  66. IVisualArea? get hostVisualArea => _hostVisualArea;
  67. set hostVisualArea(IVisualArea? value) {
  68. if (value != _hostVisualArea) {
  69. _hostVisualArea = value;
  70. }
  71. }
  72. @override
  73. bool get isActive => _isActive;
  74. set isActive(bool value) {
  75. if (value != _isActive) {
  76. _isActive = value;
  77. }
  78. }
  79. @override
  80. int get id => _id;
  81. /// 获取画布轨迹起点的角标文案,如果测量结果显示简洁注释,则会在轨迹起点显示简洁注释
  82. String get idText => _getIdText();
  83. String _getIdText() {
  84. if (featureStyle.showBriefAnnotation) {
  85. if (refItem.briefAnnotation.isNotEmpty) {
  86. return '$id.${refItem.briefAnnotation}';
  87. }
  88. }
  89. return '$id';
  90. }
  91. /// 顶点尺寸
  92. double get vertexSize =>
  93. measureData.measureSystemSetting.shapeCursorSize * refItem.scaleRatio;
  94. @override
  95. List<ValueBase> get values => _values;
  96. @override
  97. ValueBase? get value => _values.isNotEmpty ? _values.first : null;
  98. /// 更新浮点型结果值
  99. FloatValue? updateFloatValue(
  100. ItemOutputMeta outputMeta,
  101. double value,
  102. VidUsUnit unit,
  103. ) {
  104. final valueBase =
  105. values.firstWhereOrNull((e) => e.meta.name == outputMeta.name);
  106. if (valueBase == null) {
  107. final floatValue = FloatValue(outputMeta, value, unit);
  108. values.add(floatValue);
  109. return floatValue;
  110. } else {
  111. final floatValue = valueBase as FloatValue;
  112. floatValue.value = value;
  113. floatValue.unit = unit;
  114. return floatValue;
  115. }
  116. }
  117. /// 更新字符串结果值
  118. StringValue updateStringValue(
  119. ItemOutputMeta outputMeta,
  120. String value, [
  121. VidUsUnit unit = VidUsUnit.None,
  122. ]) {
  123. final valueBase = values.firstWhereOrNull((e) => e.name == outputMeta.name);
  124. if (valueBase == null) {
  125. final stringValue = StringValue(outputMeta, value, unit);
  126. values.add(stringValue);
  127. return stringValue;
  128. } else {
  129. final stringValue = valueBase as StringValue;
  130. stringValue.value = value;
  131. stringValue.unit = unit;
  132. return stringValue;
  133. }
  134. }
  135. @protected
  136. DPoint convert2ViewPoint(Size size, DPoint logicPoint) {
  137. final x = size.width * logicPoint.x;
  138. final y = size.height * logicPoint.y;
  139. return DPoint(x, y);
  140. }
  141. /// 画序号
  142. ///
  143. /// [text] 自定义序号内容
  144. @protected
  145. void drawId(Canvas canvas, Size size, [String? text]) {
  146. final String displayText;
  147. if (refItem.parent == null) {
  148. displayText = text ?? id.toString();
  149. } else {
  150. displayText = '$id.${refItem.description}';
  151. }
  152. final point = innerPoints[0];
  153. var offset = convert2ViewPoint(size, point).toOffset();
  154. return drawCustomId(canvas, size, offset, displayText);
  155. }
  156. /// 画自定义位置的序号
  157. /// [offset] 位置
  158. /// [text] 自定义序号内容
  159. @protected
  160. void drawCustomId(Canvas canvas, Size size, Offset offset, [String? text]) {
  161. final displayText = text ?? id.toString();
  162. final fontSize = 14.0 * refItem.scaleRatio; // TODO: from config
  163. final fontOffsetY = 4.0 * refItem.scaleRatio;
  164. final letterSpacing = 0.0 * refItem.scaleRatio;
  165. final style = TextStyle(
  166. fontSize: fontSize,
  167. color: MeasureColors.Primary,
  168. // fontWeight: FontWeight.bold,
  169. letterSpacing: letterSpacing,
  170. );
  171. final fontPlace = boundingTextSize(displayText, style);
  172. double transY = 0;
  173. double transX = 0;
  174. final vertexOffsetW = vertexSize / 2;
  175. if (offset.dx < fontPlace.width) {
  176. transX = fontSize + vertexOffsetW;
  177. } else {
  178. transX = -fontPlace.width - vertexOffsetW;
  179. }
  180. if (offset.dy < fontPlace.height + fontOffsetY) {
  181. transY = fontOffsetY;
  182. } else {
  183. transY = -fontPlace.height - fontOffsetY;
  184. }
  185. offset = offset.translate(transX, transY);
  186. canvas.drawText(
  187. displayText,
  188. offset,
  189. style: style,
  190. );
  191. }
  192. /// 画顶点
  193. void drawVertex(Canvas canvas, Offset offset, [bool active = false]) {
  194. canvas.drawVertex(offset, vertexSize, active: active);
  195. }
  196. /// 画顶点
  197. void drawCrossVertex(Canvas canvas, Offset offset, [bool active = false]) {
  198. canvas.drawCrossVertex(offset, vertexSize, active: active);
  199. }
  200. /// 画短横标记
  201. void drawMark(Canvas canvas, Offset offset,
  202. [bool active = false, bool ifHorizontal = true]) {
  203. canvas.drawMark(offset, vertexSize,
  204. active: active, ifHorizontal: ifHorizontal);
  205. }
  206. /// 计算文本长度
  207. static Size boundingTextSize(
  208. String text,
  209. TextStyle style, {
  210. int maxLines = 2 ^ 31,
  211. double maxWidth = double.infinity,
  212. }) {
  213. // if (Get.context == null) return Size.zero;
  214. if (text.isEmpty) return Size.zero;
  215. final TextPainter textPainter = TextPainter(
  216. textDirection: TextDirection.ltr,
  217. // locale: Localizations.localeOf(Get.context!),
  218. text: TextSpan(text: text, style: style),
  219. maxLines: maxLines,
  220. )..layout(maxWidth: maxWidth);
  221. return textPainter.size;
  222. }
  223. void _recordHistory() {
  224. if (refItem.parent == null) {
  225. final recorder = refItem.application.recorder;
  226. recorder.recordMeasureItem(refItem.meta.name);
  227. }
  228. }
  229. }