|
@@ -0,0 +1,143 @@
|
|
|
+import 'dart:math';
|
|
|
+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_metas.dart';
|
|
|
+import 'package:fis_measure/interfaces/process/items/item.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/calculator.dart';
|
|
|
+import 'package:fis_measure/process/items/item.dart';
|
|
|
+import 'package:fis_measure/process/items/item_feature.dart';
|
|
|
+import 'package:fis_measure/utils/canvas.dart';
|
|
|
+
|
|
|
+/// 连续两个线段确定一个角度
|
|
|
+class PolylineAngle extends MeasureItem<PolylineAngleFeature> {
|
|
|
+ PolylineAngle(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
|
|
|
+
|
|
|
+ static PolylineAngle createPolyAngle(ItemMeta meta, [IMeasureItem? parent]) {
|
|
|
+ PolylineAngle polygon = PolylineAngle(meta, parent);
|
|
|
+ polygon.calculator = _AngleCalc(polygon);
|
|
|
+ return polygon;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool onExecuteMouse(PointInfo args) {
|
|
|
+ if (state == ItemStates.finished) {
|
|
|
+ if (args.pointType == PointInfoType.mouseDown) {
|
|
|
+ state = ItemStates.waiting;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (state == ItemStates.waiting) {
|
|
|
+ if (args.pointType == PointInfoType.mouseDown) {
|
|
|
+ handleMouseDownWhileWaiting(args);
|
|
|
+ }
|
|
|
+ } else if (state == ItemStates.running) {
|
|
|
+ if (feature == null) return false;
|
|
|
+ if (args.pointType == PointInfoType.mouseUp) return false;
|
|
|
+
|
|
|
+ final f = feature!;
|
|
|
+
|
|
|
+ if (args.pointType == PointInfoType.mouseDown) {
|
|
|
+ f.innerPoints.add(args);
|
|
|
+ if (f.innerPoints.length == 4) {
|
|
|
+ f.innerPoints.removeLast();
|
|
|
+ doFeatureFinish();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ f.innerPoints.last = args;
|
|
|
+ }
|
|
|
+ doCalculate();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool onExecuteTouch(PointInfo args) {
|
|
|
+ // TODO: implement onExecuteTouch
|
|
|
+ throw UnimplementedError();
|
|
|
+ }
|
|
|
+
|
|
|
+ void handleMouseDownWhileWaiting(PointInfo args) {
|
|
|
+ // TODO: 判断是否当前area
|
|
|
+ // 转换为Area逻辑位置
|
|
|
+ final point = args.toAreaLogicPoint();
|
|
|
+ feature = PolylineAngleFeature(this, point);
|
|
|
+ if (args.hostVisualArea != null) {
|
|
|
+ feature!.hostVisualArea = args.hostVisualArea;
|
|
|
+ }
|
|
|
+ state = ItemStates.running;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class PolylineAngleFeature extends MeasureItemFeature {
|
|
|
+ PolylineAngleFeature(IMeasureItem refItem, DPoint point) : super(refItem) {
|
|
|
+ innerPoints.add(point.clone());
|
|
|
+ innerPoints.add(point.clone());
|
|
|
+ }
|
|
|
+ @override
|
|
|
+ void paint(Canvas canvas, Size size) {
|
|
|
+ if (innerPoints.isEmpty) return;
|
|
|
+
|
|
|
+ drawId(canvas, size);
|
|
|
+
|
|
|
+ final innerOffsets =
|
|
|
+ innerPoints.map((e) => convert2ViewPoint(size, e).toOffset()).toList();
|
|
|
+ for (var e in innerOffsets) {
|
|
|
+ drawVertex(canvas, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ final len = innerOffsets.length;
|
|
|
+ for (var i = 1; i < len; i++) {
|
|
|
+ final a = innerOffsets[i - 1];
|
|
|
+ final b = innerOffsets[i];
|
|
|
+ canvas.drawDashLine(a, b, 1, 10, paintPan);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class _AngleCalc extends Calculator<PolylineAngle, double> {
|
|
|
+ _AngleCalc(PolylineAngle ref) : super(ref);
|
|
|
+
|
|
|
+ @override
|
|
|
+ void calculate() {
|
|
|
+ if (ref.feature == null) return;
|
|
|
+
|
|
|
+ final feature = ref.feature!;
|
|
|
+ final viewport = feature.hostVisualArea!.viewport!;
|
|
|
+ final points = feature.innerPoints.map((e) => viewport.convert(e)).toList();
|
|
|
+
|
|
|
+ feature.values.clear();
|
|
|
+
|
|
|
+ double angle;
|
|
|
+ if (points.length != 3) {
|
|
|
+ angle = 0;
|
|
|
+ } else {
|
|
|
+ angle = calcAngle(points[1], points[0], points[2]);
|
|
|
+ }
|
|
|
+ for (var output in ref.meta.outputs) {
|
|
|
+ if (output.name == MeasureTypes.Angle) {
|
|
|
+ var value = roundDouble(angle, output.fractionalDigits);
|
|
|
+ feature.updateFloatValue(output, value, output.unit);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 三个点计算角度,pointsA 为顶点
|
|
|
+ static double calcAngle(DPoint pointsA, DPoint pointsB, DPoint pointsC) {
|
|
|
+ double angle = 0;
|
|
|
+ double a =
|
|
|
+ sqrt(pow(pointsB.x - pointsC.x, 2) + pow(pointsB.y - pointsC.y, 2));
|
|
|
+ double b =
|
|
|
+ sqrt(pow(pointsA.x - pointsC.x, 2) + pow(pointsA.y - pointsC.y, 2));
|
|
|
+ double c =
|
|
|
+ sqrt(pow(pointsA.x - pointsB.x, 2) + pow(pointsA.y - pointsB.y, 2));
|
|
|
+ if (a + b > c && a + c > b && b + c > a) {
|
|
|
+ double cosA = (pow(b, 2) + pow(c, 2) - pow(a, 2)) / (2 * b * c);
|
|
|
+ angle = acos(cosA) * 180 / pi;
|
|
|
+ }
|
|
|
+ return angle;
|
|
|
+ }
|
|
|
+}
|