소스 검색

calc area&perimeter PolyLine

melon.yin 2 년 전
부모
커밋
be0128181e

+ 51 - 0
lib/process/calcuators/area.dart

@@ -0,0 +1,51 @@
+import 'dart:math' as math;
+import 'package:fis_measure/interfaces/date_types/point.dart';
+import 'package:fis_measure/interfaces/process/calculators/output.dart';
+import 'package:fis_measure/interfaces/process/items/measure_terms.dart';
+import 'package:fis_measure/process/primitives/ellipse.dart';
+import 'package:vid/us/vid_us_unit.dart';
+
+import '../primitives/poyline.dart';
+import 'calculator.dart';
+
+class PolyLineAreaCal extends Calculator<PolyLine, double> {
+  PolyLineAreaCal(PolyLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    // TODO:xxx
+    final viewport = ref.feature!.hostVisualArea!.viewport!;
+    final points =
+        ref.feature!.innerPoints.map((e) => viewport.convert(e)).toList();
+
+    double value = clacArea(points);
+    final outputItem = OutputItem(
+      value: value,
+      name: MeasureTerms.Area,
+      unit: VidUsUnit.cm2,
+    );
+    final description = "${ref.description}: ${roundDouble(value)}cm²";
+    outputItem.updateDescription(description: description);
+    output = outputItem;
+  }
+
+  static double clacArea(List<DPoint> points) {
+    if (points.isEmpty) {
+      return 0;
+    }
+
+    double sum = 0;
+    var ax = points[0].x;
+    var ay = points[0].y;
+    for (var i = 1; i < points.length - 1; i++) {
+      var bx = points[i].x;
+      var by = points[i].y;
+      var cx = points[i + 1].x;
+      var cy = points[i + 1].y;
+      sum += ax * by - ay * bx + ay * cx - ax * cy + bx * cy - cx * by;
+    }
+    return (-sum / 2).abs();
+  }
+}

+ 61 - 0
lib/process/calcuators/perimeter.dart

@@ -0,0 +1,61 @@
+import 'package:fis_measure/interfaces/date_types/point.dart';
+import 'package:fis_measure/interfaces/process/calculators/output.dart';
+import 'package:fis_measure/interfaces/process/items/measure_terms.dart';
+import 'package:fis_measure/process/primitives/ellipse.dart';
+import 'package:vid/us/vid_us_unit.dart';
+
+import '../primitives/poyline.dart';
+import 'calculator.dart';
+
+class PolyLinePerimeterCal extends Calculator<PolyLine, double> {
+  PolyLinePerimeterCal(PolyLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    // TODO:xxx
+    final viewport = ref.feature!.hostVisualArea!.viewport!;
+    final points =
+        ref.feature!.innerPoints.map((e) => viewport.convert(e)).toList();
+
+    double threshold = 0;
+    // if (ref.Threshold.HasValue)
+    // {
+    //     threshold = ref.Threshold.Value;
+    // }
+    double value = calcPerimeter(points, ref.feature!.isClosed, threshold);
+    final outputItem = OutputItem(
+      value: value,
+      name: MeasureTerms.Perimeter,
+      unit: VidUsUnit.cm,
+    );
+    final description =
+        "${ref.description}: ${roundDouble(value)}${VidUsUnit.cm.name}";
+    outputItem.updateDescription(description: description);
+    output = outputItem;
+  }
+
+  static double calcPerimeter(
+    List<DPoint> points,
+    bool isClosed,
+    double threshold,
+  ) {
+    if (points.length < 2) {
+      return 0;
+    }
+
+    double sum = 0;
+    for (int i = 1, j = 0; j < points.length && i < points.length; i++) {
+      var length = (points[i] - points[j]).length;
+      if (length.abs() > threshold) {
+        sum += length;
+        j = i;
+      }
+    }
+    if (isClosed) {
+      sum += (points[points.length - 1] - points[0]).length;
+    }
+    return sum;
+  }
+}

+ 1 - 12
lib/process/primitives/ellipse.dart

@@ -1,9 +1,6 @@
 import 'dart:ui';
-
 import 'package:fis_measure/interfaces/process/items/item.dart';
-import 'package:fis_measure/interfaces/process/visuals/visual_area.dart';
 import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
-
 import '../items/item.dart';
 import '../items/item_feature.dart';
 
@@ -12,12 +9,6 @@ class Ellipse extends MeasureItem<EllipseFeature> {
 
   @override
   bool onExecuteMouse(PointInfo args) {
-    if (feature == null) {
-      if (args.hostVisualArea != null) {
-        feature = EllipseFeature(this);
-        feature!.hostVisualArea = args.hostVisualArea!;
-      }
-    }
     return true;
   }
 
@@ -31,7 +22,5 @@ class EllipseFeature extends MeasureItemFeature {
   EllipseFeature(IMeasureItem refItem) : super(refItem);
 
   @override
-  void paint(Canvas canvas, Size size) {
-    // TODO: implement paint
-  }
+  void paint(Canvas canvas, Size size) {}
 }

+ 148 - 0
lib/process/primitives/poyline.dart

@@ -0,0 +1,148 @@
+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/workspace/point_info.dart';
+import 'package:fis_measure/view/canvas/utils.dart';
+import 'package:path_drawing/path_drawing.dart';
+
+import '../calcuators/area.dart';
+import '../calcuators/perimeter.dart';
+import '../items/item.dart';
+import '../items/item_feature.dart';
+
+class PolyLine extends MeasureItem<PolyLineFeature> {
+  final bool _initialClosed = false;
+
+  PolyLine(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
+
+  @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 (args.pointType == PointInfoType.mouseUp) return false;
+
+      feature?.adopt(args);
+      doCalculate();
+      if (args.pointType == PointInfoType.mouseDown) {
+        doFeatureFinish();
+      } else {
+        _checkAutoFinish();
+      }
+    }
+    return true;
+  }
+
+  void _checkAutoFinish() {
+    double autoSnapDistance = 10; //TODO: from config
+    bool isAutoSnap = true; //TODO: from config
+    if (feature == null) return;
+    final logicStart = feature!.innerPoints.first;
+    final logicEnd = feature!.innerPoints.last;
+    if (1 == 2) {
+      feature!.innerPoints.add(feature!.innerPoints.first); // 强制闭合
+    }
+  }
+
+  void handleMouseDownWhileWaiting(PointInfo args) {
+    // TODO: 判断是否当前area
+    // 转换为Area逻辑位置
+    feature = PolyLineFeature(this);
+    feature!.isClosed = _initialClosed;
+    if (args.hostVisualArea != null) {
+      feature!.hostVisualArea = args.hostVisualArea;
+    }
+    final point = args.toAreaLogicPoint();
+    feature!.adopt(point);
+    state = ItemStates.running;
+  }
+
+  @override
+  bool onExecuteTouch(PointInfo args) {
+    return true;
+  }
+
+  /// 创建面积测量
+  static PolyLine createArea(
+    ItemMeta meta, [
+    IMeasureItem? parent,
+  ]) {
+    PolyLine poyline = PolyLine(meta, parent);
+    poyline.calculator = PolyLineAreaCal(poyline);
+    return poyline;
+  }
+
+  /// 创建周长测量
+  static PolyLine createPerimeter(
+    ItemMeta meta, [
+    IMeasureItem? parent,
+  ]) {
+    PolyLine poyline = PolyLine(meta, parent);
+    poyline.calculator = PolyLinePerimeterCal(poyline);
+    return poyline;
+  }
+}
+
+class PolyLineFeature extends MeasureItemFeature {
+  bool _isClosed = false;
+
+  PolyLineFeature(IMeasureItem refItem) : super(refItem);
+
+  /// 是否闭合?抄自超声机
+  bool get isClosed => _isClosed;
+  set isClosed(bool value) {
+    if (value != _isClosed) {
+      _isClosed = value;
+    }
+  }
+
+  /// 首节点
+  DPoint get firstPoint => innerPoints.first;
+
+  /// 接收新坐标
+  void adopt(DPoint point) {
+    innerPoints.add(point);
+  }
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (innerPoints.isEmpty) return;
+
+    // TODO: from style config
+    const double vertexSize = 10;
+
+    final points = innerPoints.map((e) => convert2ViewPoint(size, e)).toList();
+    final startPoint = points.first;
+    canvas.drawVertex(
+      startPoint.toOffset(),
+      vertexSize,
+      active: points.length == 1,
+    );
+
+    if (points.length > 1) {
+      final Path path = Path();
+      path.moveTo(startPoint.x, startPoint.y);
+      for (var i = 1; i < points.length; i++) {
+        final point = points[i];
+        path.lineTo(point.x, point.y);
+      }
+      path.lineTo(startPoint.x, startPoint.y);
+      canvas.drawPath(
+        dashPath(path, dashArray: CircularIntervalList([2.0, 10.0])),
+        paintPan,
+      );
+    }
+
+    canvas.drawVertex(points.last.toOffset(), vertexSize, active: isActive);
+  }
+}

+ 3 - 3
lib/process/workspace/application.dart

@@ -8,7 +8,6 @@ import 'package:fis_measure/interfaces/process/modes/mode.dart';
 import 'package:fis_common/event/event_type.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
 import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
-import 'package:fis_measure/process/primitives/ellipse.dart';
 import 'package:fis_measure/process/primitives/location.dart';
 import 'package:fis_measure/process/primitives/straightline.dart';
 import 'package:flutter/painting.dart';
@@ -16,6 +15,7 @@ import 'package:vid/us/vid_us_image.dart';
 import 'package:vid/us/vid_us_probe.dart';
 import 'package:vid/us/vid_us_unit.dart';
 
+import '../primitives/poyline.dart';
 import '../visual/visual.dart';
 
 class Application implements IApplication {
@@ -164,7 +164,7 @@ class Application implements IApplication {
     }
 
     if (name == MeasureTerms.Perimeter) {
-      activeItem = Ellipse(
+      activeItem = PolyLine.createPerimeter(
         ItemMeta(
           MeasureTerms.Perimeter,
           {
@@ -178,7 +178,7 @@ class Application implements IApplication {
       return;
     }
     if (name == MeasureTerms.Area) {
-      activeItem = Ellipse(
+      activeItem = PolyLine.createArea(
         ItemMeta(
           MeasureTerms.Area,
           {

+ 4 - 6
pubspec.lock

@@ -143,11 +143,9 @@ packages:
   fis_vid:
     dependency: "direct main"
     description:
-      path: "."
-      ref: "^1.0.2"
-      resolved-ref: d226cb53baf2bd0041f408ad2b8e9c522fec3cd2
-      url: "http://git.ius.plus:88/melon.yin/fis_lib_vid.git"
-    source: git
+      path: "../fis_lib_vid"
+      relative: true
+    source: path
     version: "0.0.1"
   flutter:
     dependency: "direct main"
@@ -454,5 +452,5 @@ packages:
     source: hosted
     version: "5.3.1"
 sdks:
-  dart: ">=2.16.2 <3.0.0"
+  dart: ">=2.16.0-100.0.dev <3.0.0"
   flutter: ">=2.8.1"

+ 5 - 4
pubspec.yaml

@@ -69,10 +69,11 @@ dependency_overrides:
     git:
       url: http://git.ius.plus:88/Project-Wing/flutter_vid.git
       ref: 54343a18f3
-  # fis_vid:
-  #   git:
-  #     url: http://git.ius.plus:88/melon.yin/fis_lib_vid.git
-  #     ref: d226cb53ba   
+  fis_vid:
+    # git:
+    #   url: http://git.ius.plus:88/melon.yin/fis_lib_vid.git
+    #   ref: d226cb53ba   
+    path: ../fis_lib_vid
   fis_i18n:
     git:
       url: http://git.ius.plus:88/Project-Wing/fis_lib_i18n.git