|
@@ -0,0 +1,163 @@
|
|
|
+import 'dart:ui';
|
|
|
+
|
|
|
+import 'package:fis_measure/interfaces/date_types/point.dart';
|
|
|
+import 'package:fis_measure/interfaces/enums/items.dart';
|
|
|
+import 'package:fis_measure/interfaces/process/items/item.dart';
|
|
|
+import 'package:fis_measure/interfaces/process/items/item_metas.dart';
|
|
|
+import 'package:fis_measure/interfaces/process/items/types.dart';
|
|
|
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
|
|
|
+import 'package:fis_measure/process/calcuators/heart_rate.dart';
|
|
|
+import 'package:fis_measure/process/items/item.dart';
|
|
|
+import 'package:fis_measure/utils/canvas.dart';
|
|
|
+import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
|
|
|
+import 'package:fis_measure/view/gesture/positioned_cursor.dart';
|
|
|
+import 'package:get/get.dart';
|
|
|
+import 'package:vid/us/vid_us_mode.dart';
|
|
|
+import '../items/item_feature.dart';
|
|
|
+
|
|
|
+/// 只绘制一次直线,即会自动开始,不会自动结束
|
|
|
+class SingleStraightLine extends MeasureItem<SingleStraightLineFeature> {
|
|
|
+ late final mouseState = Get.find<IMouseState>();
|
|
|
+ SingleStraightLine(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
|
|
|
+
|
|
|
+ static SingleStraightLine createHeartRate(ItemMeta meta,
|
|
|
+ [IMeasureItem? parent]) {
|
|
|
+ SingleStraightLine straightLine = SingleStraightLine(meta, parent);
|
|
|
+ straightLine.calculator = HeartRateCal(straightLine);
|
|
|
+ final point = DPoint(0, 0);
|
|
|
+ straightLine.feature = StraightLineHeartRateFeature(
|
|
|
+ straightLine, point, point, straightLine.doCalculate,
|
|
|
+ ifHorizontal: false);
|
|
|
+ print('SingleStraightLine.createHeartRate');
|
|
|
+ return straightLine;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool onExecuteMouse(PointInfo args) {
|
|
|
+ if (state == ItemStates.waiting) {
|
|
|
+ startMeasure(args);
|
|
|
+ } else if (state == ItemStates.running) {
|
|
|
+ if (args.pointType == PointInfoType.mouseUp) return false;
|
|
|
+ feature?.endPoint = args;
|
|
|
+ doCalculate();
|
|
|
+ if (args.pointType == PointInfoType.mouseDown) {
|
|
|
+ state = ItemStates.idle;
|
|
|
+
|
|
|
+ ///重置十字样式
|
|
|
+ mouseState.crossIndicatorStyleChanged
|
|
|
+ .emit(this, CrossIndicatorStyle.nomal);
|
|
|
+ }
|
|
|
+ } else if (state == ItemStates.idle) {
|
|
|
+ if (args.pointType == PointInfoType.mouseDown) {
|
|
|
+ feature?.startPoint = args;
|
|
|
+ feature?.endPoint = args;
|
|
|
+ state = ItemStates.running;
|
|
|
+
|
|
|
+ ///设置十字样式
|
|
|
+ mouseState.crossIndicatorStyleChanged
|
|
|
+ .emit(this, CrossIndicatorStyle.vertical);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool onExecuteTouch(PointInfo args) {
|
|
|
+ //TODO
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ void startMeasure(PointInfo args) {
|
|
|
+ final point = DPoint(0, 0);
|
|
|
+ if (args.hostVisualArea != null) {
|
|
|
+ handleTissueTM(args.hostVisualArea!.mode.modeType, point);
|
|
|
+ feature!.hostVisualArea = args.hostVisualArea;
|
|
|
+ }
|
|
|
+ state = ItemStates.idle;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 处理TissueTimeMotion模式
|
|
|
+ void handleTissueTM(VidUsModeType mode, DPoint point) {
|
|
|
+ if (mode == VidUsModeType.TissueTM || mode == VidUsModeType.Doppler) {
|
|
|
+ switch (meta.measureType) {
|
|
|
+ case MeasureTypes.HR:
|
|
|
+ mouseState.crossIndicatorStyleChanged
|
|
|
+ .emit(this, CrossIndicatorStyle.vertical);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ feature = SingleStraightLineFeature(this, point, point);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class SingleStraightLineFeature extends MeasureItemFeature {
|
|
|
+ SingleStraightLineFeature(
|
|
|
+ IMeasureItem refItem,
|
|
|
+ DPoint startPoint,
|
|
|
+ DPoint endPoint,
|
|
|
+ ) : super(refItem) {
|
|
|
+ innerPoints.add(startPoint);
|
|
|
+ innerPoints.add(endPoint);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 起点
|
|
|
+ DPoint get startPoint => innerPoints[0];
|
|
|
+ set startPoint(DPoint value) => innerPoints[0] = value;
|
|
|
+
|
|
|
+ /// 终点
|
|
|
+ DPoint get endPoint => innerPoints[1];
|
|
|
+ set endPoint(DPoint value) => innerPoints[1] = value;
|
|
|
+
|
|
|
+ /// 长度
|
|
|
+ double get length => (endPoint - startPoint).length;
|
|
|
+
|
|
|
+ @override
|
|
|
+ void paint(Canvas canvas, Size size) {
|
|
|
+ if (startPoint == endPoint) return;
|
|
|
+
|
|
|
+ var idText = '$id.${refItem.briefAnnotation}';
|
|
|
+ drawId(canvas, size, idText);
|
|
|
+
|
|
|
+ final startOffset = convert2ViewPoint(size, startPoint).toOffset();
|
|
|
+ drawVertex(canvas, startOffset);
|
|
|
+
|
|
|
+ final endOffset = convert2ViewPoint(size, endPoint).toOffset();
|
|
|
+ canvas.drawDashLine(startOffset, endOffset, 1, 10, paintPan);
|
|
|
+ drawVertex(canvas, endOffset, isActive);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class StraightLineHeartRateFeature extends SingleStraightLineFeature {
|
|
|
+ StraightLineHeartRateFeature(
|
|
|
+ IMeasureItem refItem, DPoint startPoint, DPoint endPoint, this.calculate,
|
|
|
+ {this.ifHorizontal = true})
|
|
|
+ : super(refItem, startPoint, endPoint);
|
|
|
+
|
|
|
+ ///心脏周期
|
|
|
+ int heartCycle = 1;
|
|
|
+ final bool ifHorizontal;
|
|
|
+ final Function calculate;
|
|
|
+ void setHeartRate(int cycle) {
|
|
|
+ heartCycle = cycle;
|
|
|
+ calculate();
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ void paint(Canvas canvas, Size size) {
|
|
|
+ if (startPoint == endPoint) return;
|
|
|
+ var idText = '$id';
|
|
|
+ drawId(canvas, size, idText);
|
|
|
+ final startOffset = convert2ViewPoint(size, startPoint).toOffset();
|
|
|
+ final endOffset = convert2ViewPoint(size, endPoint).toOffset();
|
|
|
+ if (ifHorizontal) {
|
|
|
+ drawMark(canvas, startOffset);
|
|
|
+ drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
|
|
|
+ } else {
|
|
|
+ drawMark(canvas, startOffset, false, ifHorizontal);
|
|
|
+ drawMark(
|
|
|
+ canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|