hisence-yolo-detection/XKRS.UI/Canvas.cs

1238 lines
40 KiB
C#
Raw Normal View History

2024-06-17 11:02:28 +08:00
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using XKRS.UI.Helper;
using System.Text.Json;
using System.Security.Cryptography.X509Certificates;
using System.Xml.Serialization;
using System.Drawing;
using Sunny.UI;
using Sunny.UI.Win32;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Point = System.Drawing.Point;
namespace XKRS.UI
{
public partial class Canvas : UserControl, INotifyPropertyChanged
{
#region
public event PropertyChangedEventHandler? PropertyChanged;
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion
[DisplayName("方向键移动间距")]
[Description("按下方向键时,选中的缺陷可以向对应的方向平移,该值设置按下一次方向键缺陷图片的移动距离,单位:像素")]
public float MoveStep { get; set; } = 5f;
[DisplayName("允许选中缺陷")]
[Description("鼠标单击时,是否允许选中图上绘制的缺陷,允许选中时才可以对缺陷进行操作")]
public bool AllowSelectDefect { get; set; } = true;
private Keys _keyLastPressed = Keys.None;
/// <summary>
/// 顺序查找已选中的缺陷
/// </summary>
private Defect? _selectedDefect;
public Defect SelectedDefect
{
get
{
_selectedDefect = DefectList.FirstOrDefault(d => d.Selected);
return _selectedDefect;
}
}
/// <summary>
/// 整体缩放比例
/// </summary>
private float _wholeScale;
public float WholeScale
{
get
{
return _wholeScale;
}
set
{
_wholeScale = value;
WholeScaleChange();
}
}
/// <summary>
/// 横向缩放比列
/// </summary>
private float _xScale;
public float XScale
{
get
{
return _xScale;
}
set
{
_xScale = value;
XScaleChange();
}
}
/// <summary>
/// 竖向缩放比例
/// </summary>
private float _yScale;
public float YScale
{
get
{
return _yScale;
}
set
{
_yScale = value;
YScaleChange();
}
}
/// <summary>
/// 缩放比例该参数必须大于0
/// </summary>
private double _scale = 1.0;
public double Scale
{
get { return _scale; }
set
{
if (value <= 0.000001)
{
return;
}
_scale = value;
NotifyPropertyChanged("DScale");
}
}
/// <summary>
/// 旋转角度
/// </summary>
private double _route = 0.0;
public double Route
{
get { return _route; }
set
{
_route = value;
DRouteChange();
NotifyPropertyChanged("DRoute");
}
}
/// <summary>
/// 横向移动距离
/// </summary>
private float _xMove;
public float XMove
{
get { return _xMove; }
set
{
_xMove = value;
XMoveChange();
}
}
/// <summary>
/// 竖向移动距离
/// </summary>
private float _yMove;
public float YMove
{
get { return _yMove; }
set
{
_yMove = value;
YMoveChange();
}
}
/// <summary>
/// 边框颜色
/// </summary>
private Brush _brushColor;
public Brush BrushColor
{
get
{
return _brushColor;
}
set
{
_brushColor = value;
ColorChange();
}
}
/// <summary>
/// 变换矩阵
/// </summary>
private Matrix _matrix = new Matrix();
public Matrix Matrix => _matrix.Clone();
/// <summary>
/// 矩形框
/// </summary>
private Rectangle _rcImg = new Rectangle(0, 0, 0, 0);
public int _width { get; private set; }
public int _height { get; private set; }
/// <summary>
/// 位图
/// </summary>
private Bitmap? _bitmap = null;
public Bitmap CanvasBitmap
{
get
{
return _bitmap;
}
}
/// <summary>
/// 预览缺陷图片的GraphicsPath
/// </summary>
private GraphicsPath? _path = null;
public Bitmap ImgData
{
get { return _bitmap; }
set
{
Init();
_bitmap = value;
if (null == _bitmap)
{
_rcImg.Width = 0;
_rcImg.Height = 0;
}
else
{
_rcImg.Width = _bitmap.Width;
_rcImg.Height = _bitmap.Height;
FitImage();
}
//强制控件使其工作区无效并且重新绘制自己以及任何子控件
Refresh();
}
}
private string strImgPath = string.Empty;
public string ImagePath
{
get { return strImgPath; }
set
{
try
{
if (null != _bitmap)
{
_bitmap.Dispose();
}
using (Stream s = File.Open(value, FileMode.Open))
{
ImgData = (Bitmap)Image.FromStream(s);
}
}
catch (Exception)
{
_bitmap = null;
strImgPath = string.Empty;
Refresh();
}
}
}
private Mat strImgMat = new Mat();
public Mat ImaMAt
{
get { return strImgMat; }
set
{
try
{
if (null != _bitmap)
{
_bitmap.Dispose();
}
ImgData = value.ToBitmap();
}
catch (Exception)
{
_bitmap = null;
strImgPath = string.Empty;
Refresh();
}
}
}
private PointF _panBasePoint = PointF.Empty;
private ClickArea _clickArea = ClickArea.AREA_UNKNOW;
public List<Defect> DefectList = new List<Defect>();
public List<GraphicsPath> GPathList = new List<GraphicsPath>();
Action<object, MouseEventArgs> actionMove;
Action<object, MouseEventArgs> actionUp;
Action<object, MouseEventArgs> actionDown;
//action1+=
object osender;
private Dictionary<MouseButtons, Action<object, MouseEventArgs>> _mouseEventDic = new Dictionary<MouseButtons, Action<object, MouseEventArgs>>()
{
};
public Canvas()
{
InitializeComponent();
DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint//控件忽略窗口消息 WM_ERASEBKGND 以减少闪烁
| ControlStyles.UserPaint//由控件而不是由操作系统来绘制控件自身,即自定义绘制
| ControlStyles.OptimizedDoubleBuffer//控件将首先绘制到缓冲区而不是直接绘制到屏幕,这可以减少闪烁
| ControlStyles.ResizeRedraw, true);//控件会在调整大小时进行重绘
//添加鼠标滑轮事件
//MouseWheel += OnCanvasMouseWheel;
//actionMove += ImageMoveFunc;
// actionUp += ImageUPFunc;
// actionDown += ImageDownFunc;
_mouseEventDic.Add(MouseButtons.Left, actionMove);
// _mouseEventDic.Add(MouseButtons.Left, actionMove);
// _mouseEventDic.Add(MouseButtons.Left, actionMove);
}
/// <summary>
/// 初始化
/// </summary>
private void Init()
{
_clickArea = ClickArea.AREA_UNKNOW;//枚举
_rcImg = new Rectangle(0, 0, 0, 0);
Scale = 1.0;
Route = 0.0;
_matrix.Reset();//重置为单位矩阵
strImgPath = string.Empty;
_bitmap = null;
}
protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint(e);
try
{
//获取表示控件的工作区的矩形
Rectangle rect = ClientRectangle;
Graphics oriGraphics = e.Graphics;
//设置平滑程度为高质量,减少抗锯齿的出现
oriGraphics.SmoothingMode = SmoothingMode.HighQuality;
// 双缓冲绘图
//获取当前应用程序域的 BufferedGraphicsContext此实例管理该应用程序的所有默认双缓冲
BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
//BufferedGraphics 对象管理与呈现图面(例如窗体或控件)关联的内存缓冲
BufferedGraphics myBuffer = currentContext.Allocate(oriGraphics, rect);
//实例化一个直接表示内存缓冲的 Graphics 对象,可将图形呈现到内存缓冲,绘制到此对象中
Graphics bufferGraphics = myBuffer.Graphics;
bufferGraphics.SmoothingMode = SmoothingMode.HighQuality;
//高质量低速度呈现
bufferGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
//使用的插值算法
bufferGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
//清除整个绘图面并以指定背景色填充,Console.BackColor指获取当前控件的背景色
bufferGraphics.Clear(BackColor);
bufferGraphics.MultiplyTransform(_matrix);
#region
if (_bitmap != null)
{
try
{
bufferGraphics.DrawImage(_bitmap, 0, 0, _bitmap.Width, _bitmap.Height);
if (_path != null)
{
bufferGraphics.DrawPath(new Pen(Brushes.Yellow, 1f), _path);
}
}
catch { }
}
else
{
_bitmap = null;
return;
}
#endregion
#region
GPathList.ForEach(path =>
{
if (path != null)
{
bufferGraphics.DrawPath(new Pen(Brushes.Green, 2f), path);
}
});
#endregion
#region
DefectList.ForEach(item =>
{
// 缺陷图片
Bitmap bitmapDefect = item.OriBitMap;
// 基准矩阵为背景图的矩阵
Matrix baseMatrix = _matrix.Clone();
baseMatrix.Multiply(item.PrivateMatrix); // 右乘每个缺陷自己的矩阵
bufferGraphics.Transform = baseMatrix;
PointF upperLeftPoint = item.UpperLeftPoint;
bufferGraphics.DrawImage(bitmapDefect, upperLeftPoint.X, upperLeftPoint.Y, bitmapDefect.Width, bitmapDefect.Height);
if (item.Selected)
{
// bufferGraphics.DrawPath(new Pen(Brushes.Yellow, 1f), item.Path);
item.DrawPath(bufferGraphics);
}
baseMatrix.Dispose();
});
#endregion
myBuffer.Render(oriGraphics);
//释放资源
bufferGraphics.Dispose();
myBuffer.Dispose();
currentContext.Dispose();
}
catch { }
}
/// <summary>
/// 鼠标滚轮事件
/// </summary>
private void Canvas_MouseWheel(object? sender, MouseEventArgs e)
{
//绑定滚轮键
if (_clickArea == ClickArea.AREA_UNKNOW || _clickArea == ClickArea.AREA_IMG)
{
var delta = e.Delta;
var p = e.Location.ToImageCoordinate(_matrix);
var mat = new Matrix();
mat.Translate(p.X, p.Y);
if (delta > 0)
{
mat.Scale(1.1f, 1.1f);
}
else
{
mat.Scale(0.9f, 0.9f);
}
mat.Translate(-p.X, -p.Y);
_matrix.Multiply(mat);
Refresh();
}
else if (_clickArea == ClickArea.AREA_DEFECT)
{
var delta = e.Delta;
var tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
var point = e.Location.ToImageCoordinate(tmpMatrix);
SelectedDefect.Move(point.X, point.Y);
if (delta > 0)
{
SelectedDefect.Scale(1.1f, 1.1f);
SelectedDefect.WholeDScale *= 1.1f;
SelectedDefect.XDScale *= 1.1f;
SelectedDefect.YDScale *= 1.1f;
for (int i = 0; i < SelectedDefect.LastSetScale.Length; i++)
{
SelectedDefect.LastSetScale[i] *= 1.1f;
}
}
else
{
SelectedDefect.Scale(0.9f, 0.9f);
SelectedDefect.WholeDScale *= 0.9f;
SelectedDefect.XDScale *= 0.9f;
SelectedDefect.YDScale *= 0.9f;
for (int i = 0; i < SelectedDefect.LastSetScale.Length; i++)
{
SelectedDefect.LastSetScale[i] *= 0.9f;
}
}
SelectedDefect.Move(-point.X, -point.Y);
Refresh();
}
}
/// <summary>
/// 整体缩放比列改变时触发
/// </summary>
private void WholeScaleChange()
{
if (SelectedDefect == null)
{
return;
}
float scaleWhole = WholeScale / SelectedDefect.LastSetScale[0];
SelectedDefect.LastSetScale[0] = WholeScale;
SelectedDefect.WholeDScale = WholeScale;
SelectedDefect.XDScale *= scaleWhole;
SelectedDefect.YDScale *= scaleWhole;
SelectedDefect.LastSetScale[1] *= scaleWhole;
SelectedDefect.LastSetScale[2] *= scaleWhole;
var point = SelectedDefect._defectCenterPoint;
SelectedDefect.Move(point.X, point.Y);
SelectedDefect.Scale(scaleWhole, scaleWhole);
SelectedDefect.Move(-point.X, -point.Y);
Refresh();
}
/// <summary>
/// 横向缩放比例改变时触发
/// </summary>
private void XScaleChange()
{
if (SelectedDefect == null)
{
return;
}
float scaleX = XScale / SelectedDefect.LastSetScale[1];
SelectedDefect.LastSetScale[1] = XScale;
SelectedDefect.XDScale = XScale;
var point = SelectedDefect._defectCenterPoint;
SelectedDefect.Move(point.X, point.Y);
SelectedDefect.Scale(scaleX, 1f);
SelectedDefect.Move(-point.X, -point.Y);
Refresh();
}
/// <summary>
/// 竖向缩放比例改变时触发
/// </summary>
private void YScaleChange()
{
if (SelectedDefect == null)
{
return;
}
float scaleY = YScale / SelectedDefect.LastSetScale[2];
SelectedDefect.LastSetScale[2] = YScale;
SelectedDefect.YDScale = YScale;
var point = SelectedDefect._defectCenterPoint;
SelectedDefect.Move(point.X, point.Y);
SelectedDefect.Scale(1f, scaleY);
SelectedDefect.Move(-point.X, -point.Y);
Refresh();
}
/// <summary>
/// 自适应图片,缩放到符合控件尺寸
/// </summary>
private void FitImage()
{
if (null == _bitmap)
{
return;
}
_matrix = new Matrix();
try
{
// 先将图片缩放到适配控件尺寸
// 宽高比例中的较大值
float wRatio = 1f * _bitmap.Width / Width;
float hRatio = 1f * _bitmap.Height / Height;
float ratio = 1 / Math.Max(wRatio, hRatio);
_matrix.Scale(ratio, ratio);
_width = (int)(_bitmap.Width * ratio);
_height = (int)(_bitmap.Height * ratio);
// 再将图片平移到控件中心
// 将plMain的中心转换为图片坐标
PointF pControlCenter = new(Width / 2.0f, Height / 2.0f);
PointF pImgCoordinate = pControlCenter.ToImageCoordinate(_matrix);
//目标坐标减去当前坐标
_matrix.Translate(pImgCoordinate.X - _bitmap.Width / 2.0f,
pImgCoordinate.Y - _bitmap.Height / 2.0f);
}
catch (Exception)
{
throw;
}
//强制控件使其工作区无效并立即重绘自己和任何子控件
Invalidate();
}
private void Canvas_SizeChanged(object sender, EventArgs e)
{
Refresh();
}
//{
// { MouseButtons.Left, ImageMoveFunc()},
// { MouseButtons.Right, ImageMoveFunc},
//};
// _mouseEventDic
public enum ActionEnum
{
MOVE_ACTION,
Move_Down,
Move_Up,
}
public void Set(MouseButtons btn, ActionEnum action)
{
switch (action)
{
case ActionEnum.MOVE_ACTION:
_mouseEventDic[btn] = ImageMoveFunc;
break;
case ActionEnum.Move_Up:
_mouseEventDic[btn] = ImageUPFunc;
break;
case ActionEnum.Move_Down:
_mouseEventDic[btn] = ImageDownFunc;
break;
}
}
private void ImageMoveFunc(object sender, MouseEventArgs e)
{
//鼠标左键移动触发移动事件
if (MouseButtons.Left == e.Button)
{
if (PointF.Empty == _panBasePoint)
{
return;
}
switch (_clickArea)
{
//case ClickArea.AREA_DEFECT: // 点击了缺陷区域
// {
// // 选中的缺陷
// if (null == SelectedDefect)
// {
// break;
// }
// var tmpMatrix = _matrix.Clone();
// tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
// //MouseEventArgs.Location包含相对于控件左上角的point坐标
// //得到点击的坐标在缺陷坐标系中的坐标值
// PointF p = e.Location.ToImageCoordinate(tmpMatrix);
// float x = p.X - _panBasePoint.X;
// float y = p.Y - _panBasePoint.Y;
// Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y,(int)x,(int)y);
// // 位移矩阵左乘缺陷矩阵
// SelectedDefect.Move(x, y);
// // 更新缺陷在控件坐标系中的位移
// PointF nowPoint = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix);
// PointF initialPoint = SelectedDefect.InitialPosition.ToControlCoordinate(_matrix);
// SelectedDefect.XDMove = nowPoint.X - initialPoint.X;
// SelectedDefect.YDMove = nowPoint.Y - initialPoint.Y;
// break;
// }
case ClickArea.AREA_IMG: // 点击了图像区域
{
PointF p = e.Location.ToImageCoordinate(_matrix);
float x = p.X - _panBasePoint.X;
float y = p.Y - _panBasePoint.Y;
_matrix.Translate(x, y);
break;
}
}
}
}
private void ImageUPFunc(object sender, MouseEventArgs e)
{
if (MouseButtons.Left == e.Button || MouseButtons.Right == e.Button)
{
_panBasePoint = Point.Empty;
_clickArea = ClickArea.AREA_UNKNOW;
}
}
private void ImageDownFunc(object sender, MouseEventArgs e)
{
Func<Defect, bool> funcContain = defect =>
{
// 每个图片的最终矩阵,即背景图的矩阵 右乘 缺陷自身的矩阵
var tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(defect.PrivateMatrix);
// 得到点击的坐标在每个缺陷的坐标系中的坐标值
PointF tmpP = e.Location.ToImageCoordinate(tmpMatrix);
if (defect.ContainPoint(tmpP.ToPoint())) // 点击了缺陷区域
{
_clickArea = ClickArea.AREA_DEFECT;
_panBasePoint = tmpP;
a = e.Location;
// 此时基准点的坐标系为缺陷图片的坐标系
return true;
}
return false;
};
if (AllowSelectDefect)
{
if (MouseButtons.Left == e.Button)
{
// 如果允许选中缺陷功能
// 检查是否在缺陷范围内,倒序查找
var ret = DefectList.LastOrDefault(d => funcContain(d));
if (null != ret) // 点击了缺陷
{
if (ret.Selected) // 点击的是已经选择过的缺陷
{
}
else // 点击的是未选择的缺陷
{
// 取消选择所有的,并选中当前点击的
DefectList.ForEach(d => d.UnSelect());
ret.Select();
}
return;
}
else
{
DefectList.ForEach(d => d.UnSelect());
PointF clickPoint = e.Location.ToImageCoordinate(_matrix);
if (_rcImg.Contains(clickPoint.ToPoint()))
{
_clickArea = ClickArea.AREA_IMG;
_panBasePoint = clickPoint;
}
}
}
if (e.Button == MouseButtons.Right)
{
PointF clickPoint = e.Location.ToImageCoordinate(_matrix);
if (_rcImg.Contains(clickPoint.ToPoint()))
{
if (null == SelectedDefect)
{
return;
}
_clickArea = ClickArea.AREA_IMG;
_panBasePoint = clickPoint.ToImageCoordinate(SelectedDefect.PrivateMatrix);
}
}
}
}
/// <summary>
/// 图像移动与旋转
/// </summary>
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
//鼠标左键移动触发移动事件
if (MouseButtons.Left == e.Button)
{
//_mouseEventDic[MouseButtons.Left].Invoke(sender, e);
if (PointF.Empty == _panBasePoint)
{
return;
}
switch (_clickArea)
{
//case ClickArea.AREA_DEFECT: // 点击了缺陷区域
// {
// // 选中的缺陷
// if (null == SelectedDefect)
// {
// break;
// }
// var tmpMatrix = _matrix.Clone();
// tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
// //MouseEventArgs.Location包含相对于控件左上角的point坐标
// //得到点击的坐标在缺陷坐标系中的坐标值
// PointF p = e.Location.ToImageCoordinate(tmpMatrix);
// float x = p.X - _panBasePoint.X;
// float y = p.Y - _panBasePoint.Y;
// // 位移矩阵左乘缺陷矩阵
// SelectedDefect.Move(x, y);
// // 更新缺陷在控件坐标系中的位移
// PointF nowPoint = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix);
// PointF initialPoint = SelectedDefect.InitialPosition.ToControlCoordinate(_matrix);
// SelectedDefect.XDMove = nowPoint.X - initialPoint.X;
// SelectedDefect.YDMove = nowPoint.Y - initialPoint.Y;
// break;
// }
case ClickArea.AREA_IMG: // 点击了图像区域
{
PointF p = e.Location.ToImageCoordinate(_matrix);
string log = "x:" + p.X.ToString() + "Y:" + p.Y.ToString();
WriteLog(log);
float x = p.X - _panBasePoint.X;
float y = p.Y - _panBasePoint.Y;
string log2 = "mmmx:" + x.ToString() + "mmmY:" + y.ToString();
WriteLog(log2);
//Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y, (int)x, (int)y);
// _path = new GraphicsPath();
//_path.AddRectangle(rectangle);
//_path.CloseAllFigures();
// Defect defect = new Defect(rectangle, _matrixcs);
// DefectList.Add(defect);
//PointF[] ps = new PointF[] { defect._defectCenterPoint };
// defect.PrivateMatrix.TransformPoints(ps);
// defect.InitialPosition = ps[0];
// defect.Select();
break;
}
}
}
//鼠标右键移动触发旋转事件
if (e.Button == MouseButtons.Right)
{
if (_panBasePoint == PointF.Empty || _clickArea == ClickArea.AREA_UNKNOW)
{
return;
}
switch (_clickArea)
{
case ClickArea.AREA_UNKNOW:
case ClickArea.AREA_DEFECT:
{
break;
}
case ClickArea.AREA_IMG:
{
if (SelectedDefect == null)
{
return;
}
Matrix tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
PointF p = e.Location.ToImageCoordinate(tmpMatrix);
float xBefore = _panBasePoint.X - SelectedDefect._defectCenterPoint.X;
float yBefore = _panBasePoint.Y - SelectedDefect._defectCenterPoint.Y;
float xAfter = p.X - SelectedDefect._defectCenterPoint.X;
float yAfter = p.Y - SelectedDefect._defectCenterPoint.Y;
double coorBefore = Math.Atan2(yBefore, xBefore);
double coorAfter = Math.Atan2(yAfter, xAfter);
SelectedDefect.DRoute = ((coorAfter - coorBefore) * 180 / Math.PI);
Route = SelectedDefect.DRoute;
break;
}
}
}
Refresh();
}
/// <summary>
/// 角度变化触发
/// </summary>
private void DRouteChange()
{
if (SelectedDefect == null)
{
return;
}
SelectedDefect.RotateAt((float)Route, SelectedDefect._defectCenterPoint);
SelectedDefect.TotalDRoute += Route;
Refresh();
}
private PointF a;
/// <summary>
/// 横向位移触发
/// </summary>
private void XMoveChange()
{
if (null == SelectedDefect)
{
return;
}
Matrix tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
SelectedDefect.LastSetPosition = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix);
PointF nowPoint = new PointF(SelectedDefect.LastSetPosition.X + XMove, SelectedDefect.LastSetPosition.Y);
nowPoint = nowPoint.ToImageCoordinate(tmpMatrix);
float x = nowPoint.X - SelectedDefect._defectCenterPoint.X;
float y = nowPoint.Y - SelectedDefect._defectCenterPoint.Y;
SelectedDefect.Move(x, y);
SelectedDefect.XDMove += XMove;
Refresh();
}
/// <summary>
/// 竖向位移触发
/// </summary>
private void YMoveChange()
{
if (null == SelectedDefect)
{
return;
}
Matrix tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(SelectedDefect.PrivateMatrix);
SelectedDefect.LastSetPosition = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix);
PointF nowPoint = new PointF(SelectedDefect.LastSetPosition.X, SelectedDefect.LastSetPosition.Y + YMove);
nowPoint = nowPoint.ToImageCoordinate(tmpMatrix);
int x = (int)(nowPoint.X - SelectedDefect._defectCenterPoint.X);
int y = (int)(nowPoint.Y - SelectedDefect._defectCenterPoint.Y);
SelectedDefect.Move(x, y);
SelectedDefect.YDMove += YMove;
Refresh();
}
public void ColorChange()
{
Refresh();
}
/// <summary>
/// 鼠标按下事件
/// </summary>
private void Canvas_MouseDown(object sender, MouseEventArgs e)
{
Func<Defect, bool> funcContain = defect =>
{
// 每个图片的最终矩阵,即背景图的矩阵 右乘 缺陷自身的矩阵
var tmpMatrix = _matrix.Clone();
tmpMatrix.Multiply(defect.PrivateMatrix);
// 得到点击的坐标在每个缺陷的坐标系中的坐标值
PointF tmpP = e.Location.ToImageCoordinate(tmpMatrix);
if (defect.ContainPoint(tmpP.ToPoint())) // 点击了缺陷区域
{
_clickArea = ClickArea.AREA_DEFECT;
_panBasePoint = tmpP;
a = e.Location;
// 此时基准点的坐标系为缺陷图片的坐标系
return true;
}
return false;
};
if (AllowSelectDefect)
{
if (MouseButtons.Left == e.Button)
{
// 如果允许选中缺陷功能
// 检查是否在缺陷范围内,倒序查找
var ret = DefectList.LastOrDefault(d => funcContain(d));
if (null != ret) // 点击了缺陷
{
if (ret.Selected) // 点击的是已经选择过的缺陷
{
}
else // 点击的是未选择的缺陷
{
// 取消选择所有的,并选中当前点击的
DefectList.ForEach(d => d.UnSelect());
ret.Select();
}
return;
}
else
{
//Defect rectitem=new Defect();
// DefectList.Add()
DefectList.ForEach(d => d.UnSelect());
PointF clickPoint = e.Location.ToImageCoordinate(_matrix);
if (_rcImg.Contains(clickPoint.ToPoint()))
{
_clickArea = ClickArea.AREA_IMG;
_panBasePoint = clickPoint;
}
}
}
if (e.Button == MouseButtons.Right)
{
PointF clickPoint = e.Location.ToImageCoordinate(_matrix);
if (_rcImg.Contains(clickPoint.ToPoint()))
{
if (null == SelectedDefect)
{
return;
}
_clickArea = ClickArea.AREA_IMG;
_panBasePoint = clickPoint.ToImageCoordinate(SelectedDefect.PrivateMatrix);
}
}
}
}
/// <summary>
/// 鼠标松开的事件
/// </summary>
private void Canvas_MouseUp(object sender, MouseEventArgs e)
{
if (MouseButtons.Left == e.Button || MouseButtons.Right == e.Button)
{
PointF p = e.Location.ToImageCoordinate(_matrix);
string log = "x:" + p.X.ToString() + "Y:" + p.Y.ToString();
WriteLog(log);
float x = p.X - _panBasePoint.X;
float y = p.Y - _panBasePoint.Y;
string log2 = "mmmx:" + x.ToString() + "mmmY:" + y.ToString();
WriteLog(log2);
//Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y, (int)x, (int)y);
//GraphicsPath path = new GraphicsPath();
//path.AddRectangle(rectangle);
//path.CloseAllFigures();
//GPathList.Add(path);
//Matrix _matrixcs = new Matrix();
//Defect defect = new Defect(rectangle, _matrixcs);
//DefectList.Add(defect);
//PointF[] ps = new PointF[] { defect._defectCenterPoint };
//defect.PrivateMatrix.TransformPoints(ps);
//defect.InitialPosition = ps[0];
//defect.Select();
_panBasePoint = Point.Empty;
_clickArea = ClickArea.AREA_UNKNOW;
}
}
/// <summary>
/// 载入缺陷预览图
/// </summary>
public void LoadDefect(string file, Polygon p)
{
_path = null;
PointF[] points = p.GetPoints().ToArray();
_path = new GraphicsPath();
_path.AddPolygon(points);
_path.CloseAllFigures();
ImagePath = file;
}
public void LoadDefect(string file)
{
_path = null;
ImagePath = file;
}
public void LoadPolygon(string file)
{
Matrix _matrix = new Matrix();
_path = null;
Defect defect = new Defect(file, _matrix);
DefectList.Add(defect);
Refresh();
}
public void LoadPolygon(string file, Polygon p)
{
Matrix _matrix = new Matrix();
PointF[] points = p.GetPoints().ToArray();
Defect defect = new Defect(file, points, _matrix);
DefectList.Add(defect);
PointF[] ps = new PointF[] { defect._defectCenterPoint };
defect.PrivateMatrix.TransformPoints(ps);
defect.InitialPosition = ps[0];
Refresh();
}
private void WriteLog(string log)
{
Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {log}");
}
/// <summary>
/// 删除新增缺陷
/// </summary>
public void deleteDefect()
{
var defect = DefectList.FirstOrDefault(d => d.Selected);
if (defect == null)
{
return;
}
DefectList.Remove(defect);
}
/// <summary>
/// 按键按下
/// </summary>
private void Canvas_KeyDown(object sender, KeyEventArgs e)
{
if (SelectedDefect == null)
{
return;
}
switch (e.KeyCode)
{
case Keys.Left:
{
SelectedDefect.Move(-MoveStep, 0, MatrixOrder.Append);
}
break;
case Keys.Up:
{
SelectedDefect.Move(0, -MoveStep, MatrixOrder.Append);
}
break;
case Keys.Right:
{
SelectedDefect.Move(MoveStep, 0, MatrixOrder.Append);
}
break;
case Keys.Down:
{
SelectedDefect.Move(0, MoveStep, MatrixOrder.Append);
}
break;
case Keys.Delete:
{
DefectList.Remove(SelectedDefect);
break;
}
default:
break;
}
Refresh();
}
/// <summary>
/// 按键抬起
/// </summary>
private void Canvas_KeyUp(object sender, KeyEventArgs e)
{
_keyLastPressed = Keys.None;
}
/// <summary>
/// 重写 ProcessDialogKey 使控件可以监听方向键与删除键
/// </summary>
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Up || keyData == Keys.Down ||
keyData == Keys.Left || keyData == Keys.Right || keyData == Keys.Delete)
{
return false;
}
else
{
return base.ProcessDialogKey(keyData);
}
}
}
}