123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // ignore_for_file: constant_identifier_names
- import 'dart:math' as math;
- import 'package:fis_measure/interfaces/date_types/point.dart';
- import 'package:fis_measure/interfaces/enums/annotation.dart';
- import 'package:fis_measure/interfaces/process/workspace/application.dart';
- import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'annotation.dart';
- /// 箭头注释
- class ArrowAnnotation extends AnnotationItem<ArrowAnnotationItemFeature> {
- ArrowAnnotation() : super(AnnotationType.arrow);
- @override
- bool onExecuteMouse(PointInfo args) {
- if (state == AnnotationStates.finish) {
- state = AnnotationStates.waiting;
- }
- if (state == AnnotationStates.waiting) {
- if (args.pointType == PointInfoType.mouseDown) {
- feature = ArrowAnnotationItemFeature(this, args);
- state = AnnotationStates.running;
- return true;
- } else {
- return false;
- }
- } else {
- if (args.pointType == PointInfoType.mouseUp) return false;
- feature?.endPoint = args;
- if (args.pointType == PointInfoType.mouseDown) {
- doFeatureFinish();
- }
- }
- return true;
- }
- PointInfo? startPoint;
- @override
- bool onExecuteTouch(PointInfo args) {
- if (state == AnnotationStates.finish) {
- if (args.pointType == PointInfoType.touchDown) {
- state = AnnotationStates.waiting;
- }
- }
- if (state == AnnotationStates.waiting) {
- switch (args.pointType) {
- case PointInfoType.touchDown:
- startPoint = args; // 设置线段起点
- break;
- case PointInfoType.touchUp:
- break; // 按下立即抬起无事发生
- case PointInfoType.touchMove:
- feature = ArrowAnnotationItemFeature(this, startPoint as DPoint);
- state = AnnotationStates.running; // 通过设置的起点开始一个绘制事件
- break;
- default:
- break;
- }
- } else if (state == AnnotationStates.running) {
- if (args.pointType == PointInfoType.touchUp) {
- doFeatureFinish();
- }
- if (args.pointType == PointInfoType.touchMove) {
- feature?.endPoint = args;
- }
- }
- // if (state == AnnotationStates.waiting) {
- // if (args.pointType == PointInfoType.mouseDown) {
- // feature = ArrowAnnotationItemFeature(this, args);
- // state = AnnotationStates.running;
- // return true;
- // } else {
- // return false;
- // }
- // } else {
- // if (args.pointType == PointInfoType.mouseUp) return false;
- // feature?.endPoint = args;
- // if (args.pointType == PointInfoType.mouseDown) {
- // doFeatureFinish();
- // }
- // }
- return true;
- }
- }
- class ArrowAnnotationItemFeature extends AnnotationItemFeature {
- static const C_ARRPW_ANGLE = 90.0; // 箭头角度
- static const C_ARROW_LENGTH = 8.0; // 中心线交叉点到终点的长度
- final _paint = Paint()
- ..color = Colors.yellow
- ..strokeWidth = 2
- ..style = PaintingStyle.stroke;
- ArrowAnnotationItemFeature(ArrowAnnotation ref, DPoint offset) : super(ref) {
- points.addAll([offset]);
- }
- DPoint get endPoint => points[1];
- set endPoint(DPoint value) {
- if (points.length > 1) {
- points[1] = value;
- } else {
- points.add(value);
- }
- }
- DPoint get startPoint => position;
- @override
- void paint(Canvas canvas, Size size) {
- double arrowLen =
- C_ARROW_LENGTH * Get.find<IApplication>().displayScaleRatio;
- final startOffset = startPoint.scale2Size(size).toOffset();
- final Offset endOffset;
- if (points.length < 2 || startPoint == endPoint) {
- endOffset = startOffset - const Offset(0, -1);
- } else {
- endOffset = points[1].scale2Size(size).toOffset();
- }
- canvas.drawLine(startOffset, endOffset, _paint);
- _drawArrow(canvas, startOffset, endOffset, arrowLen);
- }
- /// 绘制箭头
- void _drawArrow(Canvas canvas, Offset p1, Offset p2, double arrowLength) {
- final directionX = (p2.dx - p1.dx); // X轴向量方向
- final directionY = (p2.dy - p1.dy); // Y轴向量方向
- final center = _findArrowHeadCenter(p1, p2, arrowLength);
- const cuspAngle = C_ARRPW_ANGLE / 2; // 边线和中心线的角度
- const cuspRadians = cuspAngle * (math.pi / 180);
- // 边角到中心交叉点的距离
- final distanceCenter2Side = math.tan(cuspRadians) * arrowLength;
- final tan2AxisX = (p2.dy - p1.dy) / (p2.dx - p1.dx);
- // 中心线到X轴的弧度
- final radians2AxisX = math.atan(tan2AxisX).abs();
- // 在画布正坐标计算边点
- // 边点到X轴的距离
- final distance2AxisX = math.sin(radians2AxisX) * distanceCenter2Side;
- // 边点到Y轴的距离
- final distance2AxisY = math.cos(radians2AxisX) * distanceCenter2Side;
- double xRight = 0, yRight = 0;
- double xLeft = 0, yLeft = 0;
- if (directionX < 0) {
- if (directionY > 0) {
- // 右上->左下
- xRight = center.dx - distance2AxisX;
- yRight = center.dy - distance2AxisY;
- xLeft = center.dx + distance2AxisX;
- yLeft = center.dy + distance2AxisY;
- } else {
- // 右下->左上
- xRight = center.dx + distance2AxisX;
- yRight = center.dy - distance2AxisY;
- xLeft = center.dx - distance2AxisX;
- yLeft = center.dy + distance2AxisY;
- }
- } else {
- if (directionY > 0) {
- // 左上->右下
- xRight = center.dx - distance2AxisX;
- yRight = center.dy + distance2AxisY;
- xLeft = center.dx + distance2AxisX;
- yLeft = center.dy - distance2AxisY;
- } else {
- // 左下->右上
- xRight = center.dx + distance2AxisX;
- yRight = center.dy + distance2AxisY;
- xLeft = center.dx - distance2AxisX;
- yLeft = center.dy - distance2AxisY;
- }
- }
- final leftSidePoint = Offset(xLeft, yLeft);
- final rightSidePoint = Offset(xRight, yRight);
- canvas.drawLine(p2, leftSidePoint, _paint);
- canvas.drawLine(p2, rightSidePoint, _paint);
- }
- /// 找到箭头底部(两个边角的水平线)与直线的交叉点
- Offset _findArrowHeadCenter(Offset p1, Offset p2, double arrowLength) {
- final x1 = p1.dx, x2 = p2.dx;
- final y1 = p1.dy, y2 = p2.dy;
- // - 假设交叉点: p3 = (x3,y3)
- // ratio = distanc(p3-p2)/distance(p2-p1)
- // - 同时
- // ratio == (x3-x2)/(x1-x2)
- // ratio == (y3-y2)/(y1-y2)
- // - 可得
- // x3 = (x1-x2)*ratio + x2
- // y3 = (y1-y2)*ratio + y2
- final lineLength = (p2 - p1).distance;
- final ratio = arrowLength / lineLength;
- final dx = (ratio * (x1 - x2)) + x2;
- final dy = (ratio * (y1 - y2)) + y2;
- return Offset(dx, dy);
- }
- }
|