import 'package:fis_common/event/event_type.dart'; import 'package:fis_measure/interfaces/date_types/point.dart'; import 'package:fis_measure/interfaces/process/calculators/calculator.dart'; import 'package:fis_measure/interfaces/process/calculators/output.dart'; import 'package:fis_measure/interfaces/process/calculators/values.dart'; import 'package:fis_measure/interfaces/process/items/item.dart'; import 'package:fis_measure/process/items/item.dart'; import 'package:fis_measure/process/items/item_feature.dart'; import 'package:flutter/foundation.dart'; import 'package:vid/us/vid_us_unit.dart'; abstract class Calculator implements ICalculator { late T _ref; Calculator(T ref) { _ref = ref; } T get ref => _ref; @override var outputChanged = FEventHandler?>(); @override void finishOnce() {} @override Future calculateAsync() async {} @protected FloatValue? updateFloatValue( double value, { VidUsUnit? unit, bool useUnitY = false, bool useRound = false, }) { if (ref.feature == null) return null; final feature = ref.feature! as MeasureItemFeature; if (unit == null) { final viewport = feature.hostVisualArea!.viewport!; unit = useUnitY ? viewport.yUnit : viewport.xUnit; } final output = ref.meta.outputs.first; final val = useRound ? roundDouble(value, output.fractionalDigits) : value; return feature.updateFloatValue( ref.meta.outputs.first, val, unit, ); } @protected StringValue? updateStringValue(String value) { if (ref.feature == null) return null; final feature = ref.feature! as MeasureItemFeature; return feature.updateStringValue(ref.meta.outputs.first, value); } /// 对double四舍五入 double roundDouble(double value, [int digits = 2]) { final digitsStr = value.toStringAsFixed(digits); final result = double.parse(digitsStr); return result; } /// 获取结果精度 @protected int getResultDigits(OutputItem item) { int fractionalDigits = 2; VidUsUnit? targetUnit = item.unit; switch (targetUnit) { case VidUsUnit.mm: fractionalDigits = 3; break; case VidUsUnit.mm2: fractionalDigits = 4; break; case VidUsUnit.mm3: fractionalDigits = 5; break; case VidUsUnit.msec: fractionalDigits = 3; break; default: // fractionalDigits = GetConfigDigits(item); break; } return fractionalDigits; } @protected double? pickChildFloatValue(MeasureItem item) { if (item.calculator == null) return null; ValueBase? value; if (item.measuredFeatures.isNotEmpty) { value = item.measuredFeatures.first.value; } else if (item.feature != null) { value = item.feature!.value; } if (value != null) { return (value as FloatValue).value ?? 0; } return null; } @protected FloatValue? pickChildToFloatValue(MeasureItem item) { if (item.calculator == null) return null; ValueBase? value; if (item.measuredFeatures.isNotEmpty) { value = item.measuredFeatures.first.value; } else if (item.feature != null) { value = item.feature!.value; } if (value != null) { return value as FloatValue; } return null; } @protected TF? findChildFeature(MeasureItem child) { if (child.measuredFeatures.isNotEmpty) { return child.measuredFeatures.first as TF; } return child.feature as TF?; } DPoint convertTimeMotionPoint(MeasureItemFeature feature, DPoint point) { final viewport = feature.hostVisualArea!.viewport!; final layout = feature.hostVisualArea!.displayRegion; final pointClone = point.clone(); pointClone.addOffset(-layout.left, -layout.top); final physicalPoint = viewport.convert(pointClone); final coordinateOffset = viewport.region; final y = -physicalPoint.y + coordinateOffset.top; final x = physicalPoint.x + coordinateOffset.left; return DPoint(x, y); } }