123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import 'dart:math';
- import 'dart:ui';
- import 'package:vector_math/vector_math.dart';
- 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 TwolineAngle extends MeasureItem<TwolineAngleFeature> {
- TwolineAngle(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
- static TwolineAngle createTwolineAngle(ItemMeta meta,
- [IMeasureItem? parent]) {
- TwolineAngle polygon = TwolineAngle(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 == 5) {
- 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 = TwolineAngleFeature(this, point);
- if (args.hostVisualArea != null) {
- feature!.hostVisualArea = args.hostVisualArea;
- }
- state = ItemStates.running;
- }
- }
- class TwolineAngleFeature extends MeasureItemFeature {
- TwolineAngleFeature(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();
- final len = innerOffsets.length;
- if (len == 2 || len == 3) {
- final a = innerOffsets[0];
- final b = innerOffsets[1];
- canvas.drawLine(a, b, paintLinePan);
- } else if (len >= 4) {
- final a = innerOffsets[0];
- final b = innerOffsets[1];
- final c = innerOffsets[2];
- final d = innerOffsets[3];
- canvas.drawLine(a, b, paintLinePan);
- canvas.drawLine(c, d, paintLinePan);
- //向量 A、B
- final vecA = Vector2(b.dx - a.dx, b.dy - a.dy);
- final vecB = Vector2(d.dx - c.dx, d.dy - c.dy);
- //计算向量夹角
- final angle = vecA.angleToSigned(vecB);
- //计算射线cd的角度
- final vecBAngle = vecB.angleToSigned(Vector2(1, 0));
- // 计算射线ab与射线cd的交点
- final p = _getIntersection(a, b, c, d);
- // 绘制角度
- canvas.drawArc(Rect.fromCircle(center: p, radius: 30), -vecBAngle, -angle,
- false, paintLinePan);
- //如果交点在线段外,线段要延长至交点
- Offset p1 = _getIntersection(a, b, p, Offset(0, p.dy));
- final vecA1 = Vector2(p1.dx - a.dx, p1.dy - a.dy).normalized() * 50;
- p1 += Offset(vecA1.x, vecA1.y);
- Offset p2 = _getIntersection(c, d, p, Offset(0, p.dy));
- final vecB1 = Vector2(p2.dx - c.dx, p2.dy - c.dy).normalized() * 50;
- p2 += Offset(vecB1.x, vecB1.y);
- canvas.drawLine(a, p1, paintLinePan);
- canvas.drawLine(c, p2, paintLinePan);
- }
- }
- /// 计算射线ab与射线cd的交点
- Offset _getIntersection(Offset a, Offset b, Offset c, Offset d) {
- final x1 = a.dx;
- final y1 = a.dy;
- final x2 = b.dx;
- final y2 = b.dy;
- final x3 = c.dx;
- final y3 = c.dy;
- final x4 = d.dx;
- final y4 = d.dy;
- final x =
- ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) /
- ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
- final y =
- ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) /
- ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
- return Offset(x, y);
- }
- }
- class _AngleCalc extends Calculator<TwolineAngle, double> {
- _AngleCalc(TwolineAngle 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 != 4) {
- angle = 0;
- } else {
- angle = calcAngle(points[0], points[1], points[2], points[3]);
- }
- for (var output in ref.meta.outputs) {
- if (output.name == MeasureTypes.Angle) {
- var value = roundDouble(angle, output.fractionalDigits);
- feature.updateFloatValue(output, value, output.unit);
- }
- }
- }
- static double calcAngle(
- DPoint pointsA, DPoint pointsB, DPoint pointsC, DPoint pointsD) {
- double finalAngleDegree = 0;
- //向量 A、B
- final vecA = Vector2(pointsB.x - pointsA.x, pointsB.y - pointsA.y);
- final vecB = Vector2(pointsD.x - pointsC.x, pointsD.y - pointsC.y);
- //计算向量夹角
- final angle = vecA.angleToSigned(vecB);
- //转换为角度
- finalAngleDegree = angle * 180 / pi;
- if (finalAngleDegree < 0) {
- finalAngleDegree = -finalAngleDegree;
- }
- return finalAngleDegree;
- }
- }
|