hisence-yolo-detection/XKRS.UI/Canvas.cs
2024-06-17 11:02:28 +08:00

1238 lines
40 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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