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
|
|||
|
};
|
|||
|
}
|
|||
|
}
|