167 lines
4.8 KiB
C#
167 lines
4.8 KiB
C#
using System;
|
||
using Avalonia;
|
||
using Avalonia.Controls;
|
||
using Avalonia.Controls.Shapes;
|
||
using Avalonia.Input;
|
||
using Avalonia.Media;
|
||
|
||
namespace DispenserUI.Views.Controls;
|
||
|
||
public class ROISelector : Canvas
|
||
{
|
||
public static readonly StyledProperty<Point> ROICenterProperty =
|
||
AvaloniaProperty.Register<ROISelector, Point>(nameof(ROICenter));
|
||
|
||
private Path centerPath;
|
||
private EllipseGeometry circle;
|
||
private Point circleCenter;
|
||
private Path circlePath;
|
||
private Point currentPoint;
|
||
private bool isDragging;
|
||
private bool isMouseDragged;
|
||
private bool isDrawingComplete;
|
||
private bool isPositionChangeable;
|
||
private bool isRadiusChangeable;
|
||
|
||
public Point ROICenter
|
||
{
|
||
get => GetValue(ROICenterProperty);
|
||
set => SetValue(ROICenterProperty, value);
|
||
}
|
||
|
||
public ROISelector()
|
||
{
|
||
this.GetObservable(ROICenterProperty).Subscribe(val =>
|
||
{
|
||
DrawROI();
|
||
});
|
||
}
|
||
|
||
private double Get2PointsDistance(Point firstPoint, Point secondPoint)
|
||
{
|
||
return Math.Pow(Math.Pow(secondPoint.X - firstPoint.X, 2) + Math.Pow(secondPoint.Y - firstPoint.Y, 2), 0.5);
|
||
}
|
||
|
||
public new void OnPointerPressed(PointerPressedEventArgs e)
|
||
{
|
||
var pointerPoint = e.GetCurrentPoint(this);
|
||
//鼠标左键按下
|
||
if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed)
|
||
{
|
||
isDragging = true; //开启拖动
|
||
//未绘制ROI区域,可以开始绘制
|
||
if (isDrawingComplete == false)
|
||
{
|
||
circleCenter = e.GetPosition(this);
|
||
}
|
||
//已经绘制ROI区域,可以修改区域
|
||
else
|
||
{
|
||
currentPoint = e.GetPosition(this);
|
||
var distance = Get2PointsDistance(currentPoint, circleCenter);
|
||
|
||
//点击圆内位置,移动圆位置
|
||
if (distance < circle.RadiusX)
|
||
isPositionChangeable = true;
|
||
//点击圆外30像素以内位置,改变圆半径
|
||
else if (distance > circle.RadiusX && distance < circle.RadiusX + 30) isRadiusChangeable = true;
|
||
}
|
||
}
|
||
|
||
e.Handled = false;
|
||
}
|
||
|
||
public new void OnPointerReleased(PointerReleasedEventArgs e)
|
||
{
|
||
var pointerPoint = e.GetCurrentPoint(this);
|
||
// 鼠标左键释放:结束绘制
|
||
if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased)
|
||
{
|
||
isDragging = false; //结束拖动
|
||
if (isMouseDragged == true)
|
||
{
|
||
isDrawingComplete = true; //绘制完成
|
||
isMouseDragged = false;
|
||
}
|
||
|
||
isRadiusChangeable = false;
|
||
isPositionChangeable = false;
|
||
}
|
||
//鼠标右键释放:确定数据,清除图像
|
||
else if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased)
|
||
{
|
||
isPositionChangeable = false;
|
||
isRadiusChangeable = false;
|
||
isDrawingComplete = false;
|
||
Children.Remove(circlePath);
|
||
ROICenter = new Point(circleCenter.X, circleCenter.Y);
|
||
}
|
||
|
||
e.Handled = false;
|
||
}
|
||
|
||
public new void OnPointerMoved(PointerEventArgs e)
|
||
{
|
||
if (isDragging == false) return;
|
||
isMouseDragged = true;
|
||
currentPoint = e.GetPosition(this);
|
||
DrawROI();
|
||
e.Handled = false;
|
||
}
|
||
|
||
|
||
private void DrawROI()
|
||
{
|
||
Children.Remove(circlePath);
|
||
Children.Remove(centerPath);
|
||
//绘制ROI
|
||
if (isDrawingComplete == false)
|
||
{
|
||
var radius = Get2PointsDistance(currentPoint, circleCenter);
|
||
DrawCircle(circleCenter, radius);
|
||
}
|
||
else if (isPositionChangeable)
|
||
{
|
||
var radius = circle.RadiusX;
|
||
circleCenter = currentPoint;
|
||
DrawCircle(circleCenter, radius);
|
||
}
|
||
else if (isRadiusChangeable)
|
||
{
|
||
var radius = Get2PointsDistance(currentPoint, circleCenter);
|
||
DrawCircle(circleCenter, radius);
|
||
}
|
||
|
||
Children.Add(circlePath);
|
||
Children.Add(centerPath);
|
||
}
|
||
|
||
private void DrawCircle(Point center, double radius)
|
||
{
|
||
circle = new EllipseGeometry
|
||
{
|
||
Center = center,
|
||
RadiusX = radius,
|
||
RadiusY = radius
|
||
};
|
||
circlePath = new Path
|
||
{
|
||
Data = circle,
|
||
Stroke = Brushes.Orange,
|
||
StrokeThickness = 2
|
||
};
|
||
var centerPoint = new EllipseGeometry
|
||
{
|
||
Center = center,
|
||
RadiusX = 2,
|
||
RadiusY = 2,
|
||
};
|
||
centerPath = new Path
|
||
{
|
||
Data = centerPoint,
|
||
Stroke = Brushes.Orange,
|
||
Fill = Brushes.Orange,
|
||
StrokeThickness = 2
|
||
};
|
||
}
|
||
} |