using CanFly.Canvas.Helper;
using CanFly.Canvas.Model;
using CanFly.Canvas.Shape;
using LabelSharp.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MethodInvoker = System.Windows.Forms.MethodInvoker;



namespace CanFly.Canvas.UI
{
    public partial class FlyCanvas : UserControl
    {
        public event Action OnMenuItemCopyToHere;
        public event Action OnMenuItemMoveToHere;


        public event Action<int, Point> zoomRequest;
        public event Action<float> ZoomRequestF;
        public event Action<int, int> scrollRequest;
        public event Action newShape;
        public event Action<List<FlyShape>> selectionChanged;
        public event Action ShapeMoved;
        public event Action<List<FlyShape>> OnShapeMoving;
        public event Action<bool> DrawingPolygon;
        public event Action<bool> vertexSelected;
        public event Action<PointF> mouseMoved;

        public event Action<FlyShape> OnShapeUpdateEvent;


        public ShapeTypeEnum _createMode = ShapeTypeEnum.Polygon;
        public bool _fill_drawing = false;


        private float epsilon = 8.0f;
        private DoubleClickActionEnum double_click = DoubleClickActionEnum.Close;
        private int num_backups = 10;
        private bool _isEditMode = true;

        public List<FlyShape> Shapes { get; set; } = new List<FlyShape>();

        /// <summary>
        /// 外部绘制的
        /// </summary>
        public List<FlyShape> OutsideShapes { get; set; } = new List<FlyShape>();

        public List<List<FlyShape>> shapesBackups = new();
        private FlyShape? current = null;
        public List<FlyShape> selectedShapes = new List<FlyShape>();
        private List<FlyShape> selectedShapesCopy = new List<FlyShape>();

        private FlyShape line = new FlyShape();
        private PointF prevPoint;
        private PointF prevMovePoint;
        private PointF[] offsets = new PointF[2] { new PointF(), new PointF() };

        private float MOVE_SPEED = 5.0f;


        /// <summary>
        /// 是否允许多选
        /// </summary>
        public bool AllowMultiSelect { get; set; } = false;

        public int _width { get; private set; }
        public int _height { get; private set; }


        //public List<ContextMenuStrip> MenuStripsWithoutSelection = new List<ContextMenuStrip>();
        //public List<ContextMenuStrip> MenuStripsWithSelection = new List<ContextMenuStrip>();



        /// <summary>
        /// 缩放比例,该参数必须大于0
        /// </summary>
        private float _scale = 1.0f;

        public new float Scale
        {
            get { return _scale; }
            set
            {

                if (value <= 0.0001)
                {
                    return;
                }
                _scale = value;
                ZoomRequestF?.Invoke(_scale);
            }
        }


        public Bitmap? pixmap;// = new Bitmap();

        private Dictionary<Shape.FlyShape, bool> visible = new Dictionary<Shape.FlyShape, bool>();
        private bool _hideBackround = false;
        private bool hideBackround = false;

        #region 高亮显示的图形

        private Shape.FlyShape? hShape;
        private Shape.FlyShape? prevhShape;
        private int hVertex = -1;
        private int prevhVertex = -1;
        private int hEdge;
        private int prevhEdge;

        #endregion

        private bool movingShape = false;
        private bool snapping = true;
        private bool hShapeIsSelected = false;
        private Graphics _painter;

        private Cursor _cursor = CustomCursors.CURSOR_DEFAULT;
        private Cursor _preCursor = CustomCursors.CURSOR_DEFAULT;


        /// <summary>
        /// 点击的区域
        /// </summary>
        internal enum ClickArea
        {

            /// <summary>
            /// 未知区域
            /// </summary>
            AREA_UNKNOW,


            /// <summary>
            /// 图片区域
            /// </summary>
            AREA_IMG,


            /// <summary>
            /// 缺陷元素区域
            /// </summary>
            AREA_DEFECT,
        }
        private ClickArea _clickArea = ClickArea.AREA_UNKNOW;


        /// <summary>
        /// 矩形框
        /// </summary>
        private Rectangle _rcImg = new Rectangle(0, 0, 0, 0);


        /// <summary>
        /// 变换矩阵
        /// </summary>
        private Matrix _matrix = new Matrix();


        public Matrix Matrix => _matrix.Clone();



        //private Bitmap image;
        //private List<Rectangle> rectangles = new List<Rectangle>();
        //private Rectangle currentRectangle;
        //private bool drawing = false;


        public FlyCanvas()
        {

            InitializeComponent();

            // this.KeyDown += FlyCanvas_KeyDown;
            // this.KeyPress += FlyCanvas_KeyPress;

            this.DoubleBuffered = true;
            SetStyle(ControlStyles.AllPaintingInWmPaint//控件忽略窗口消息 WM_ERASEBKGND 以减少闪烁
                | ControlStyles.UserPaint//由控件而不是由操作系统来绘制控件自身,即自定义绘制
                | ControlStyles.OptimizedDoubleBuffer//控件将首先绘制到缓冲区而不是直接绘制到屏幕,这可以减少闪烁
                | ControlStyles.ResizeRedraw, true);//控件会在调整大小时进行重绘



            //InitTask();

        }



        private void Init()
        {
            _clickArea = ClickArea.AREA_UNKNOW;//枚举
            _rcImg = new Rectangle(0, 0, 0, 0);

            _matrix.Reset();//重置为单位矩阵
                            // strImgPath = string.Empty;
            pixmap = null;

        }



        public bool FillDrawing
        {
            get { return _fill_drawing; }
            set { _fill_drawing = value; }
        }



        /// <summary>
        /// 图形类型
        /// </summary>
        public ShapeTypeEnum CreateMode
        {
            get { return _createMode; }
            set { _createMode = value; }
        }


        public void StoreShapes()
        {
            var shapesBackup = new List<Shape.FlyShape>();
            foreach (var shape in Shapes)
            {
                shapesBackup.Add(shape.Copy());
            }
            // 限制备份数量
            if (shapesBackups.Count >= num_backups)
            {
                shapesBackups.RemoveRange(0, shapesBackups.Count - num_backups + 1); // 移除多余的备份
            }

            shapesBackups.Add(shapesBackup); // 添加当前备份
        }



        public bool IsShapeRestorable
        {
            get
            {
                if (shapesBackups.Count < 2)
                {
                    return false;
                }
                return true;
            }
        }



        public void RestoreShape()
        {
            if (!this.IsShapeRestorable)
            {
                return;
            }

            // 确保备份不为空
            if (shapesBackups.Count == 0)
            {
                return; // 如果没有备份,直接返回
            }

            shapesBackups.RemoveAt(shapesBackups.Count - 1);
            // 弹出最新的备份
            List<Shape.FlyShape> shapesBackup = shapesBackups[^1]; // 获取最后的备份而不移除它
            shapesBackups.RemoveAt(shapesBackups.Count - 1); // 移除最新的备份

            // 恢复形状
            this.Shapes = shapesBackup;
            this.selectedShapes = new List<Shape.FlyShape>(); // 清空选中的形状

            foreach (Shape.FlyShape shape in Shapes)
            {
                shape.Selected = false; // 取消所有形状的选中状态
            }

            Invalidate();
        }



        public bool IsVisible(FlyShape shape)
        {
            if (visible.Keys.Contains(shape))
            {
                return visible[shape];
            }
            return true;
        }


        public bool Drawing() => !_isEditMode;

        public bool Editing() => _isEditMode;



        private void UnHighlight()
        {
            if (hShape != null)
            {
                hShape.HighlightClear();
                Invalidate();
            }
            prevhShape = hShape;
            prevhVertex = hVertex;
            prevhEdge = hEdge;

            hShape = null;
            hVertex = -1;
            hEdge = -1;
        }


        public bool SelectedVertex() => hVertex >= 0;
        public bool SelectedEdge() => hEdge >= 0;





        private void DeSelectShape()
        {
            if (this.selectedShapes != null)
            {
                this.SetHiding(false);

                {
                    this.selectedShapes.ForEach(shape => shape.Selected = false);
                    this.selectedShapes.Clear();
                }

                this.selectionChanged?.Invoke(new List<FlyShape>());
                this.hShapeIsSelected = false;
                Invalidate();
            }
        }


        public List<FlyShape> DeleteSelected()
        {
            List<Shape.FlyShape> deleted_shapes = new List<Shape.FlyShape>();
            if (this.selectedShapes != null)
            {
                foreach (var shape in this.selectedShapes)
                {
                    this.Shapes.Remove(shape);
                    deleted_shapes.Add(shape);
                }
                this.StoreShapes();
                this.selectedShapes = new List<Shape.FlyShape>();
                Invalidate();
            }
            return deleted_shapes;
        }


        private void DeleteShape(Shape.FlyShape shape)
        {
            if (this.selectedShapes.Contains(shape))
            {
                this.selectedShapes.Remove(shape);
            }
            if (this.Shapes.Contains(shape))
            {
                this.Shapes.Remove(shape);
            }
            this.StoreShapes();
            Invalidate();
        }


        public void LoadImage(string path)
        {
            //image = new Bitmap(path);
            //this.Invalidate();
        }




        private PointF _panBasePoint = PointF.Empty;




        private void Finalise()
        {
            this.current.Close();

            this.Shapes.Add(this.current);
            this.StoreShapes();
            this.current = null;
            this.SetHiding(false);
            newShape?.Invoke();
            Invalidate();
        }



        private void SetHiding(bool enable = true)
        {
            this._hideBackround = enable ? this.hideBackround : false;
        }


        private void FlyCanvas_MouseWheel(object? sender, MouseEventArgs e)
        {
            // base.OnMouseWheel(e);
            //绑定滚轮键
            if (_clickArea == ClickArea.AREA_UNKNOW || _clickArea == ClickArea.AREA_IMG)
            {
                var delta = e.Delta;
                float scaleFactor = delta > 0 ? 1.1f : 0.9f;
                Scale *= scaleFactor;
                if (Scale >= 10)
                {
                    return;
                }

                var p = e.Location.ToImageCoordinate(_matrix);
                var mat = new Matrix();
                mat.Translate(p.X, p.Y);

                mat.Scale(scaleFactor, scaleFactor);

                mat.Translate(-p.X, -p.Y);
                _matrix.Multiply(mat);

                Refresh();
            }
        }


        #region


        private bool OutputOfPixmap(PointF p)
        {
            var w = this.pixmap.Width;
            var h = this.pixmap.Height;
            return !(p.X >= 0 && p.X <= (w - 1) && p.Y >= 0 && p.Y <= (h - 1));
        }




        public FlyShape SetLastLabel(string text, object flags)
        {
            int index = Shapes.Count - 1;
            Shapes[index].label = text;
            Shapes[index].flags = flags;
            shapesBackups.RemoveAt(shapesBackups.Count - 1);
            StoreShapes();
            return Shapes[index];
        }



        public void UndoLastLine()
        {
            current = Shapes[^1];
            Shapes.RemoveAt(Shapes.Count - 1);
            current.SetOpen();


            // TODO: 
            switch (CreateMode)
            {

                case ShapeTypeEnum.Polygon:
                case ShapeTypeEnum.LineStrip:
                    line.Points = new List<PointF> { current[^1], current[0] };
                    break;

                case ShapeTypeEnum.Rectangle:
                case ShapeTypeEnum.Line:
                case ShapeTypeEnum.Circle:
                    current.Points = new List<PointF> { current.Points[0] };
                    break;

                case ShapeTypeEnum.Point:
                    current = null;
                    break;

                default:
                    break;
            }


            DrawingPolygon?.Invoke(true);


        }



        public void UndoLastPoint()
        {
            if (current == null || current.IsClosed())
            {
                return;
            }
            current.PopPoint();
            if (current.Length > 0)
            {
                line[0] = current[-1];
            }
            else
            {
                current = null;
                DrawingPolygon?.Invoke(false);
            }
            Invalidate();
        }



        public void LoadPixmap(Bitmap pixmap, bool clear_shapes = true)
        {
            if (this.pixmap != null)
            {
                this.pixmap.Dispose();
            }
            Init();
            this.pixmap = pixmap;
            _rcImg.Width = this.pixmap.Width;
            _rcImg.Height = this.pixmap.Width;

            if (clear_shapes)
            {
                Shapes = new List<Shape.FlyShape>();
            }
            FitImage();
            this.BackColor = Color.Gray;
            Refresh();

            this.Focus();
        }



        /// <summary>
        /// 自适应图片,缩放到符合控件尺寸
        /// </summary>
        public void FitImage()
        {
            if (null == this.pixmap)
            {
                return;
            }

            _matrix = new Matrix();

            try
            {
                // 先将图片缩放到适配控件尺寸
                // 宽高比例中的较大值
                float wRatio = 1f * pixmap.Width / Width;
                float hRatio = 1f * pixmap.Height / Height;
                float ratio = 1 / Math.Max(wRatio, hRatio);


                _matrix.Scale(ratio, ratio);
                _width = (int)(pixmap.Width * ratio);
                _height = (int)(pixmap.Height * ratio);

                // 再将图片平移到控件中心
                // 将plMain的中心转换为图片坐标
                PointF pControlCenter = new(Width / 2.0f, Height / 2.0f);
                PointF pImgCoordinate = pControlCenter.ToImageCoordinate(_matrix);

                //目标坐标减去当前坐标
                _matrix.Translate(pImgCoordinate.X - pixmap.Width / 2.0f,
                     pImgCoordinate.Y - pixmap.Height / 2.0f);

            }
            catch (Exception)
            {
                throw;
            }

            //强制控件使其工作区无效并立即重绘自己和任何子控件
            Invalidate();
        }

        public void LoadShapes(List<Shape.FlyShape> shapes, bool replace = true)
        {
            if (replace)
            {
                this.Shapes = new List<Shape.FlyShape>(shapes);
            }
            else
            {
                shapes.AddRange(shapes);
            }
            StoreShapes();
            current = null;
            hShape = null;
            hVertex = -1;
            hEdge = -1;
            Invalidate();
        }



        public void SetShapeVisible(Shape.FlyShape shape, bool value)
        {
            visible[shape] = value;
            Invalidate();
        }


        #endregion


        private void Canvas_SizeChanged(object sender, EventArgs e)
        {
            Invalidate();
        }


        private void OverrideCursor(Cursor cursor)
        {
            RestoreCursor();
            _preCursor = _cursor;
            _cursor = cursor;
            this.Cursor = cursor;
        }


        private void RestoreCursor()
        {
            this._cursor = _preCursor;
            this.Cursor = this._cursor;
        }


        public void ResetState()
        {
            this.RestoreCursor();
            this.pixmap = null;
            this.shapesBackups = new();
            this.Invalidate();
        }




        /// <summary>
        /// 鼠标按下事件
        /// </summary> 
        private void FlyCanvas_MouseDown(object? sender, MouseEventArgs e)
        {
            PointF pos = e.Location.ToImageCoordinate(_matrix);

            bool is_shift_pressed = (ModifierKeys & Keys.Shift) == Keys.Shift;

            if (MouseButtons.Left == e.Button)
            {
                if (Drawing())
                {
                    if (current != null) // 画后续的点
                    {
                        switch (CreateMode)
                        {
                            case ShapeTypeEnum.Polygon:
                                {
                                    if (!this.line[1].Equals(current[-1]))
                                    {
                                        this.current.AddPoint(this.line[1]);
                                        this.line[0] = this.current[-1];
                                        if (this.current.IsClosed())
                                        {
                                            this.Finalise();
                                        }
                                    }
                                }
                                break;

                            case ShapeTypeEnum.Rectangle: // 矩形
                                {
                                    this.current.Points = this.line.Points;
                                    OnShapeUpdateEvent?.Invoke(this.current);
                                    this.Finalise();
                                
                                    break;
                                }
                            case ShapeTypeEnum.Circle:
                            case ShapeTypeEnum.Line:
                                {
                                    this.current.Points = this.line.Points;
                                    OnShapeUpdateEvent?.Invoke(this.current);
                                    this.Finalise();
                                }
                                break;

                            case ShapeTypeEnum.LineStrip:
                                {
                                    this.current.AddPoint(this.line[1]);
                                    this.line[0] = this.current[-1];
                                    if ((ModifierKeys & Keys.Control) == Keys.Control)
                                    {
                                        this.Finalise();
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                    else if (!OutputOfPixmap(pos))  // 画第一个点
                    {
                        this.current = new FlyShape()
                        {
                            ShapeType = this.CreateMode,
                        };

                        this.current.AddPoint(pos, is_shift_pressed ? 0 : 1);

                        if (CreateMode == ShapeTypeEnum.Point) // 画点
                        {
                            this.Finalise();
                        }
                        else // 画其他图形
                        {
                            if (this.CreateMode == ShapeTypeEnum.Circle)
                            {
                                this.current.ShapeType = ShapeTypeEnum.Circle;
                            }
                            this.line.Points = new List<PointF>() { pos, pos };
                            this.line.point_labels = new List<int> { 1, 1 };
                            this.SetHiding();
                            this.DrawingPolygon?.Invoke(true);

                        }
                    }
                }
                else if (Editing())
                {
                    if (this.SelectedEdge() && ((ModifierKeys & Keys.Alt) == Keys.Alt))
                    {
                        this.AddPointToEdge();
                    }
                    else if (this.SelectedVertex()
                        && ((ModifierKeys & Keys.Alt) == Keys.Alt)
                        && ((ModifierKeys & Keys.Shift) == Keys.Shift))
                    {
                        this.RemoveSelectedPoint();
                    }


                    bool group_mode = false;
                    if (AllowMultiSelect)
                    {
                        group_mode = (ModifierKeys & Keys.Control) == Keys.Control;
                    }
                    this.SelectShapePoint(pos, group_mode);
                    this.prevPoint = pos;
                    Invalidate();
                } // else if (Editing())
            } // if (MouseButtons.Left == e.Button)
            else if (MouseButtons.Right == e.Button && this.Editing())
            {
                bool group_mode = false;
                if (AllowMultiSelect)
                {
                    group_mode = (ModifierKeys & Keys.Control) == Keys.Control;
                }

                if (this.selectedShapes == null
                    || (this.hShape != null && !this.selectedShapes.Contains(this.hShape)))
                {
                    this.SelectShapePoint(pos, group_mode);
                    Invalidate();
                }
                this.prevPoint = pos;


            } // else if (MouseButtons.Right == e.Button && this.Editing())
            else if (MouseButtons.Middle == e.Button)
            {

                if (_rcImg.Contains(pos.ToPoint()))
                {
                    _clickArea = ClickArea.AREA_IMG;
                    _panBasePoint = pos;
                }

            } // else if (MouseButtons.Middle == e.Button)


            Refresh();
        }


        private void FlyCanvas_MouseUp(object? sender, MouseEventArgs e)
        {
            if (MouseButtons.Left == e.Button || MouseButtons.Right == e.Button)
            {
                _panBasePoint = Point.Empty;
                _clickArea = ClickArea.AREA_UNKNOW;
            }

            if (e.Button == MouseButtons.Right)
            {
                // menuWithSelection.Show(this, e.Location);
            }
            else if (e.Button == MouseButtons.Left)
            {
                if (this.Editing())
                {
                    if (this.hShape != null && this.hShapeIsSelected && !this.movingShape)
                    {
                        var shps = this.selectedShapes.Where(shp => !shp.Equals(this.hShape)).ToList();
                        this.selectedShapes.ForEach(shp => shp.Selected = false);
                        this.selectedShapes = shps;
                        this.selectedShapes.ForEach(shp => shp.Selected = true);
                        this.selectionChanged?.Invoke(this.selectedShapes);
                    }
                }
                AfterMouseRelease();
            }
        }


        /// <summary>
        /// 鼠标移动事件
        /// </summary>
        private void FlyCanvas_OnMouseMove(object? sender, MouseEventArgs e)
        {
            PointF pos = e.Location.ToImageCoordinate(_matrix);

            mouseMoved?.Invoke(pos);

            this.prevMovePoint = pos;
            RestoreCursor();

            bool is_shift_pressed = (ModifierKeys & Keys.Shift) == Keys.Shift;


            if (Drawing()) // 绘图状态
            {
                this.line.ShapeType = this.CreateMode;
                this.OverrideCursor(CustomCursors.CURSOR_DRAW);

                if (this.current == null)
                {
                    return;
                }

                if (this.OutputOfPixmap(pos))
                {
                    // TODO: 处理超出边界的情况
                }
                else if (this.snapping
                    && this.current.Length > 1
                    && this.CreateMode == ShapeTypeEnum.Polygon
                    && this.CloseEnough(pos, this.current[0]))
                {
                    pos = this.current[0];
                    this.OverrideCursor(CustomCursors.CURSOR_POINT);
                    this.current.HighlightVertex(0, HighlightModeEnum.NEAR_VERTEX);
                }


                switch (CreateMode)
                {
                    case ShapeTypeEnum.Polygon:
                    case ShapeTypeEnum.LineStrip:
                        {
                            this.line.Points = new() { this.current[-1], pos };
                            this.line.point_labels = new() { 1, 1 };
                        }
                        break;
                    //                    case ShapeTypeEnum.Rectangle: // 矩形
                    //                        {
                    //#if false // 改动5
                    //                            float minX = Math.Min(this.current[0].X, pos.X);
                    //                            float maxX = Math.Max(this.current[0].X, pos.X);
                    //                            float minY = Math.Min(this.current[0].Y, pos.Y);
                    //                            float maxY = Math.Max(this.current[0].Y, pos.Y);

                    //                            List<PointF> tmpPoints = new List<PointF>() {
                    //                               new PointF(minX, minY),
                    //                               new PointF(maxX, minY),  
                    //                               new PointF(maxX, maxY),  
                    //                                new PointF(minX, maxY),  
                    //                            };

                    //                            this.line.Points = tmpPoints;
                    //#else
                    //                            this.line.Points = new() { this.current[0], pos };
                    //#endif
                    //                            this.line.point_labels = new() { 1, 1 };
                    //                            this.line.Close();
                    //                        }
                    //                        break;

                    case ShapeTypeEnum.Rectangle: // 矩形
                        {
#if false
                            float minX = Math.Min(this.current[0].X, pos.X);
                            float maxX = Math.Max(this.current[0].X, pos.X);
                            float minY = Math.Min(this.current[0].Y, pos.Y);
                            float maxY = Math.Max(this.current[0].Y, pos.Y);

                            List<PointF> tmpPoints = new List<PointF>() {
                               new PointF(minX, minY),
                               new PointF(maxX, minY),
                               new PointF(maxX, maxY),
                               new PointF(minX, maxY),
                            };

                            this.line.Points = tmpPoints;
#else
                            this.line.Points = new() { this.current[0], pos };
#endif
                            this.line.point_labels = new() { 1, 1 };
                            this.line.Close();
                        }
                        break;
                    case ShapeTypeEnum.Circle:
                        {
                            this.line.Points = new() { this.current[0], pos };
                            this.line.point_labels = new() { 1, 1 };
                            this.line.ShapeType = ShapeTypeEnum.Circle;
                            OnShapeUpdateEvent?.Invoke(this.line);
                        }
                        break;
                    case ShapeTypeEnum.Line:
                        {
                            this.line.Points = new() { this.current[0], pos };
                            this.line.point_labels = new() { 1, 1 };
                            this.line.Close();
                            OnShapeUpdateEvent?.Invoke(this.line);
                        }
                        break;

                    case ShapeTypeEnum.Point:
                        {
                            this.line.Points = new() { this.current[0] };
                            this.line.point_labels = new() { 1 };
                            this.line.Close();
                        }
                        break;

                    default:
                        break;
                }
                Refresh();
                this.current.HighlightClear();
                return;
            }


            // 多边形复制移动
            if (e.Button == MouseButtons.Right)
            {
                if (this.selectedShapesCopy != null
                    && this.selectedShapesCopy.Count > 0
                    && this.prevPoint != null)
                {
                    this.OverrideCursor(CustomCursors.CURSOR_MOVE);
                    this.BoundedMoveShapes(this.selectedShapesCopy, pos);
                }
                else if (this.selectedShapes != null && this.selectedShapes.Count > 0)
                {
                    this.selectedShapesCopy = this.selectedShapes.Select(shp => shp.Copy()).ToList();
                }
                Invalidate();
                return;
            }


            // 多边形/节点 移动
            if (e.Button == MouseButtons.Left)
            {
                if (this.SelectedVertex())
                {
                    this.BoundedMoveVertex(pos);
                    Invalidate();
                    this.movingShape = true;
                }
                else if (this.selectedShapes != null
                    && this.selectedShapes.Count > 0
                    && this.prevPoint != null)
                {
                    this.OverrideCursor(CustomCursors.CURSOR_MOVE);
                    this.BoundedMoveShapes(this.selectedShapes, pos);
                    OnShapeMoving?.Invoke(this.selectedShapes);
                    Invalidate();
                    this.movingShape = true;
                }
                return;
            }



            //# Just hovering over the canvas, 2 possibilities:
            //# - Highlight shapes
            //# - Highlight vertex
            //# Update shape/vertex fill and tooltip value accordingly.
            var tmpShapes = this.Shapes.Where(shp => this.IsVisible(shp)).Reverse();
            if (tmpShapes.Any())
            {
                bool found = false;

                foreach (var shape in tmpShapes)
                {
                    // 寻找距离鼠标最近的节点
                    int index = shape.NearestVertex(pos, this.epsilon);
                    int index_edge = shape.NearestEdge(pos, this.epsilon);
                    if (index >= 0)
                    {
                        if (this.SelectedVertex())
                        {
                            this.hShape?.HighlightClear();
                        }
                        this.prevhVertex = this.hVertex = index;
                        this.prevhShape = this.hShape = shape;
                        this.prevhEdge = this.hEdge;
                        this.hEdge = -1;
                        shape.HighlightVertex(index, HighlightModeEnum.MOVE_VERTEX);
                        this.OverrideCursor(CustomCursors.CURSOR_POINT);
                        // TODO: Tooltip

                        Invalidate();
                        found = true;
                        break;
                    }
                    else if (index_edge >= 0 && shape.CanAddPoint())
                    {
                        if (this.SelectedVertex())
                        {
                            this.hShape?.HighlightClear();
                        }
                        this.prevhVertex = this.hVertex;
                        this.hVertex = -1;
                        this.prevhShape = this.hShape = shape;
                        this.prevhEdge = this.hEdge = index_edge;
                        this.OverrideCursor(CustomCursors.CURSOR_POINT);
                        // TODO: Tooltip
                        Invalidate();
                        found = true;
                        break;
                    }
                    else if (shape.ContainsPoint(pos))
                    {
                        if (this.SelectedVertex())
                        {
                            this.hShape?.HighlightClear();
                        }
                        this.prevhVertex = this.hVertex;
                        this.hVertex = -1;
                        this.prevhShape = this.hShape = shape;
                        this.prevhEdge = this.hEdge;
                        this.hEdge = -1;
                        this.OverrideCursor(CustomCursors.CURSOR_GRAB);
                        Invalidate();
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    UnHighlight();
                }

                this.vertexSelected?.Invoke(this.hVertex >= 0);
            }

            // 鼠标中键移动触发移动事件
            if (MouseButtons.Middle == e.Button)
            {
                if (PointF.Empty == _panBasePoint)
                {
                    return;
                }

                switch (_clickArea)
                {
                    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;
                        }
                }
            }

            Refresh();

        }



        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(Color.FromArgb(0xf0, 0xf0, 0xf0));

                bufferGraphics.MultiplyTransform(_matrix);


                #region 画背景图

                if (pixmap != null)
                {
                    try
                    {
                        bufferGraphics.DrawImage(pixmap, 0, 0, pixmap.Width, pixmap.Height);
                        //if (_path != null)
                        //{
                        //    bufferGraphics.DrawPath(new Pen(Brushes.Yellow, 1f), _path);
                        //}
                    }
                    catch { }
                }
                else
                {
                    pixmap = null;
                    return;
                }

                #endregion





                #region   

                foreach (var shape in Shapes)
                {
                    if ((shape.Selected || !this._hideBackround)
                        && this.IsVisible(shape))
                    {
                        shape.fill = shape.Selected || (shape == this.hShape);
                        shape.Paint(bufferGraphics);
                    }
                }

                if (this.current != null)
                {
                    this.current.Paint(bufferGraphics);
                    this.line.Paint(bufferGraphics);
                }

                if (this.selectedShapesCopy != null)
                {
                    foreach (var s in this.selectedShapesCopy)
                    {
                        s.Paint(bufferGraphics);
                    }
                }

                // TODO:
                this.FillDrawing = true;

                if (this.FillDrawing
                    && this.CreateMode == ShapeTypeEnum.Polygon
                    && this.current != null
                    && this.current.Length >= 2)
                {
                    var drawing_shape = this.current.Copy();
                    if (drawing_shape.fill_color.A == 0)
                    {
                        drawing_shape.fill_color = Color.FromArgb(64, drawing_shape.fill_color);
                    }
                    drawing_shape.AddPoint(this.line[1]);
                    drawing_shape.fill = true;
                    drawing_shape.Paint(bufferGraphics);
                }


                #endregion

                #region 绘制外部传递的图形

                // this.OutsideShapes.ForEach(shp => shp.Paint(bufferGraphics));
                for (int i = 0; i < OutsideShapes.Count; i++)
                {
                    OutsideShapes[i].Paint(bufferGraphics);
                }


                #endregion


                myBuffer.Render(oriGraphics);
                //释放资源
                bufferGraphics.Dispose();
                myBuffer.Dispose();
                currentContext.Dispose();
            }
            catch (Exception ex)
            {
                throw;
            }
        }




        private void SelectShapePoint(PointF point, bool multiple_selection_mode)
        {
            if (this.SelectedVertex())
            {
                this.hShape?.HighlightVertex(this.hVertex, HighlightModeEnum.MOVE_VERTEX);
            }
            else
            {
                List<Shape.FlyShape> reversedShapes = Shapes.ToList();
                reversedShapes.Reverse();
                foreach (var shape in reversedShapes)
                {
                    if (this.IsVisible(shape) && shape.ContainsPoint(point))
                    {
                        this.SetHiding();
                        if (this.selectedShapes.Contains(shape))
                        {
                            this.hShapeIsSelected = true;
                        }
                        else
                        {
                            if (multiple_selection_mode)
                            {
                                shape.Selected = true;
                                this.selectedShapes.Add(shape);
                                this.selectionChanged?.Invoke(this.selectedShapes);
                            }
                            else
                            {
                                shape.Selected = true;
                                this.selectedShapes = new List<FlyShape>() { shape };
                                this.selectionChanged?.Invoke(this.selectedShapes);
                            }
                            this.hShapeIsSelected = false;
                        }
                        return;
                    }
                }
            }
            this.DeSelectShape();
        }

        private void RemoveSelectedPoint()
        {
            throw new NotImplementedException();
        }

        private void AddPointToEdge()
        {
            throw new NotImplementedException();
        }

        private bool BoundedMoveShapes(List<FlyShape> shapes, PointF pos)
        {
            if (this.OutputOfPixmap(pos))
            {
                return false;
            }

            PointF o1 = new PointF(
                pos.X + this.offsets[0].X,
                pos.Y + this.offsets[0].Y);
            if (this.OutputOfPixmap(o1))
            {
                pos = new PointF(
                    pos.X - Math.Min(0, o1.X),
                    pos.Y - Math.Min(0, o1.Y));
            }

            PointF o2 = new PointF(
               pos.X + this.offsets[1].X,
               pos.Y + this.offsets[1].Y);
            if (this.OutputOfPixmap(o1))
            {
                pos = new PointF(
                    pos.X + Math.Min(0, this.pixmap.Width - o2.X),
                    pos.Y + Math.Min(0, this.pixmap.Height - o2.Y));
            }

            try
            {
                PointF dp = new PointF(pos.X - this.prevPoint.X, pos.Y - this.prevPoint.Y);
                foreach (FlyShape shape in shapes)
                {
                    shape.MoveBy(dp);
                }
                this.prevPoint = pos;
                return true;
            }
            catch
            {
            }
            return false;
        }


        private void BoundedMoveVertex(PointF pos)
        {
            PointF point = this.hShape[this.hVertex];
            if (this.OutputOfPixmap(pos))
            {
                pos = this.IntersectionPoint(point, pos);
            }
            this.hShape.IsVertexMoving = true;
            this.hShape.MoveVertexBy(this.hVertex, new PointF(pos.X - point.X, pos.Y - point.Y));
            OnShapeUpdateEvent?.Invoke(hShape);
        }


        private PointF IntersectionPoint(PointF p1, PointF p2)
        {
            Size size = this.pixmap.Size;
            List<PointF> points = new List<PointF>()
            {
                new PointF(0, 0),
                new PointF(size.Width - 1, 0),
                new PointF(size.Width - 1, size.Height - 1),
                new PointF(0, size.Height - 1),
            };

            float x1 = Math.Min(Math.Max(p1.X, 0), size.Width - 1);
            float y1 = Math.Min(Math.Max(p1.Y, 0), size.Height - 1);

            float x2 = p2.X;
            float y2 = p2.Y;

            // Get the intersection details
            var intersections = IntersectingEdges(
                new PointF(x1, y1),
                new PointF(x2, y2),
                points);
            var closestIntersection = intersections.OrderBy(result => result.distance).FirstOrDefault();

            if (closestIntersection.Equals(default((double distance, int index, PointF intersectionPoint))))
            {
                return PointF.Empty; // No intersection found
            }

            var (d, i, intersection) = closestIntersection;

            // Define the edge points
            float x3 = points[i].X;
            float y3 = points[i].Y;
            float x4 = points[(i + 1) % 4].X;
            float y4 = points[(i + 1) % 4].Y;

            if (intersection == new PointF(x1, y1))
            {
                // Handle cases where the previous point is on one of the edges.
                if (x3 == x4)
                {
                    return new PointF(x3, Math.Min(Math.Max(0, y2), Math.Max(y3, y4)));
                }
                else // y3 == y4
                {
                    return new PointF(Math.Min(Math.Max(0, x2), Math.Max(x3, x4)), y3);
                }
            }

            return intersection;
        }


        private IEnumerable<(double distance, int index, PointF intersectionPoint)> IntersectingEdges(PointF point1, PointF point2, List<PointF> points)
        {
            float x1 = point1.X;
            float y1 = point1.Y;
            float x2 = point2.X;
            float y2 = point2.Y;

            for (int i = 0; i < 4; i++)
            {
                float x3 = points[i].X;
                float y3 = points[i].Y;
                float x4 = points[(i + 1) % 4].X;
                float y4 = points[(i + 1) % 4].Y;

                float denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
                float nua = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
                float nub = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);

                if (denom == 0)
                {
                    continue;
                }

                float ua = nua / denom;
                float ub = nub / denom;

                if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
                {
                    float x = x1 + ua * (x2 - x1);
                    float y = y1 + ua * (y2 - y1);
                    PointF m = new PointF((x3 + x4) / 2, (y3 + y4) / 2);
                    float d = PointHelper.Distance(m, new PointF(x2, y2));
                    yield return (d, i, new PointF(x, y));
                }

            }



        }


        private bool CloseEnough(PointF p1, PointF p2)
        {
            var d1 = PointHelper.Distance(p1, p2);
            //var d2 = (this.epsilon / this.Scale);
            //return d1 < d2;
            // TODO:
            //return false;
            return d1 < 16;
        }





        private void InitTask()
        {
            TaskFactory taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning);
            taskFactory.StartNew(MenuWithSelectionEvent);
        }



        private void AfterMouseRelease()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(AfterMouseRelease));
                return;
            }

            if (this.movingShape && this.hShape != null)
            {
                this.hShape.IsVertexMoving = false;
                int index = this.Shapes.IndexOf(this.hShape);

                if (shapesBackups.Count > 0)
                {
                    if (this.shapesBackups[this.shapesBackups.Count - 1][index].Points
              != this.Shapes[index].Points)
                    {
                        this.StoreShapes();
                        this.ShapeMoved?.Invoke();
                    }
                }



                this.movingShape = false;
            }
        }


        private bool CanCloseShape()
        {
            var b1 = this.Drawing();
            var b2 = this.current != null && this.current.Length > 2;

            return b1 && b2;
        }



        private void FlyCanvas_MouseDoubleClick(object? sender, MouseEventArgs e)
        {
            if (this.double_click != DoubleClickActionEnum.Close)
            {
                return;
            }

            if (this.CreateMode == ShapeTypeEnum.Polygon && this.CanCloseShape())
            {
                this.Finalise();
            }
        }


        //private List<Shape.FlyShape> TestReflect()
        //{
        //    List<Shape.FlyShape> shapes = new List<Shape.FlyShape>();
        //    List<string> names = new List<string>();


        //    // 获取对象的类型
        //    Type type = this.GetType();

        //    // 获取所有公共字段
        //    FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
        //    foreach (var field in fields)
        //    {
        //        if (field.FieldType.IsSubclassOf(typeof(Shape.FlyShape)) || field.FieldType == typeof(Shape.FlyShape))
        //        {
        //            shapes.Add((Shape.FlyShape)field.GetValue(this));
        //            names.Add(field.Name);
        //        }
        //    }

        //    // 获取所有公共属性
        //    PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
        //    foreach (var property in properties)
        //    {
        //        if (property.PropertyType.IsSubclassOf(typeof(Shape.FlyShape)) || property.PropertyType == typeof(Shape.FlyShape))
        //        {
        //            shapes.Add((Shape.FlyShape)property.GetValue(this));
        //            names.Add(property.Name);
        //        }
        //    }

        //    return shapes;
        //}



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

        //protected override void OnKeyDown(KeyEventArgs e)


        private void FlyCanvas_KeyPress(object? sender, KeyPressEventArgs e)
        {
            //var modifiers = e.Modifiers;
            //var key = e.KeyCode;

            Debug.WriteLine("");

            //if (this.Drawing())
            //{
            //    if (key == Keys.Escape && this.current != null)
            //    {
            //        this.current = null;
            //        this.DrawingPolygon?.Invoke(false);
            //        this.Invalidate();
            //    }
            //    else if (key == Keys.Return && this.CanCloseShape())
            //    {
            //        this.Finalise();
            //    }
            //    else if ((ModifierKeys & Keys.Alt) == Keys.Alt)
            //    {
            //        this.snapping = false;
            //    }
            //}
            //else if (Editing())
            //{
            //    switch (key)
            //    {
            //        case Keys.Up:
            //            this.MoveByKeyboard(new PointF(0f, -MOVE_SPEED));
            //            break;
            //        case Keys.Down:
            //            this.MoveByKeyboard(new PointF(0f, MOVE_SPEED));
            //            break;
            //        case Keys.Left:
            //            this.MoveByKeyboard(new PointF(-MOVE_SPEED, 0f));
            //            break;
            //        case Keys.Right:
            //            this.MoveByKeyboard(new PointF(MOVE_SPEED, 0f));
            //            break;

            //        case Keys.Delete:
            //            DeleteSelected();
            //            Invalidate();
            //            break;


            //        default:
            //            break;
            //    }
            //}
        }



        private void FlyCanvas_KeyDown(object? sender, KeyEventArgs e)
        {
            var modifiers = e.Modifiers;
            var key = e.KeyCode;

            if (this.Drawing())
            {
                if (key == Keys.Escape && this.current != null)
                {
                    this.current = null;
                    this.DrawingPolygon?.Invoke(false);
                    this.Invalidate();
                }
                else if (key == Keys.Return && this.CanCloseShape())
                {
                    this.Finalise();
                }
                else if ((ModifierKeys & Keys.Alt) == Keys.Alt)
                {
                    this.snapping = false;
                }
            }
            else if (Editing())
            {
                switch (key)
                {
                    case Keys.Up:
                        this.MoveByKeyboard(new PointF(0f, -MOVE_SPEED));
                        break;
                    case Keys.Down:
                        this.MoveByKeyboard(new PointF(0f, MOVE_SPEED));
                        break;
                    case Keys.Left:
                        this.MoveByKeyboard(new PointF(-MOVE_SPEED, 0f));
                        break;
                    case Keys.Right:
                        this.MoveByKeyboard(new PointF(MOVE_SPEED, 0f));
                        break;

                    case Keys.Delete:
                        DeleteSelected();
                        Invalidate();
                        break;


                    default:
                        break;
                }
            }
        }

        private void MoveByKeyboard(PointF offset)
        {
            if (this.selectedShapes == null)
            {
                return;
            }

            this.BoundedMoveShapes(this.selectedShapes,
                new PointF(this.prevPoint.X + offset.X, this.prevPoint.Y + offset.Y));
            this.Invalidate();
            this.movingShape = true;

        }



        /// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                isControlAlive = false; // 设置标志,停止循环
                menuCloseEvent.Set(); // 唤醒等待的线程,确保退出循环
                components.Dispose();
            }
            base.Dispose(disposing);
        }


        #region 右键菜单点击事件



        private bool isControlAlive = true;
        private bool menuWithSelectionItemClicked = false;
        private AutoResetEvent menuCloseEvent = new(false);



        private void MenuWithSelectionEvent()
        {
            while (isControlAlive)
            {
                try
                {
                    bool ret = menuCloseEvent.WaitOne();

                    if (!ret)
                    {
                        continue;
                    }

                    if (menuWithSelectionItemClicked) // 点击了菜单项
                    {
                        menuWithSelectionItemClicked = false;
                    }
                    else if (this.selectedShapesCopy != null && this.selectedShapesCopy.Count > 0) // 未点击菜单项
                    {
                        this.selectedShapesCopy = new List<Shape.FlyShape>();
                        Invalidate();
                        AfterMouseRelease();
                    }
                }
                catch
                {
                }
            }
        }


        #region 选择了Shape时的右键菜单点击事件




        private void menuItemCopyToHere_Click(object sender, EventArgs e)
        {
            OnMenuItemCopyToHere?.Invoke();
            AfterMouseRelease();

        }

        private void menuItemMoveToHere_Click(object sender, EventArgs e)
        {
            OnMenuItemMoveToHere?.Invoke();
            AfterMouseRelease();
        }


        private void menuWithSelection_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            menuCloseEvent.Set();
            Debug.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}\t menuWithSelection_Closed");
        }



        private void menuWithSelection_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            menuWithSelectionItemClicked = true;
            Debug.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}\t menuWithSelection_ItemClicked");
        }

        #endregion

        #endregion


        public bool EndMove(bool copy)
        {
            if (!(this.selectedShapes != null && this.selectedShapes.Count > 0
                && this.selectedShapesCopy != null && this.selectedShapesCopy.Count > 0
                && this.selectedShapesCopy.Count == this.selectedShapes.Count))
            {
                return false;
            }


            if (copy)
            {
                for (int i = 0; i < this.selectedShapesCopy.Count; i++)
                {
                    Shape.FlyShape shape = this.selectedShapesCopy[i];
                    this.Shapes.Add(shape);
                    this.selectedShapes[i].Selected = false;
                    this.selectedShapes[i] = shape;
                }
            }
            else
            {
                for (int i = 0; i < this.selectedShapesCopy.Count; i++)
                {
                    var shape = this.selectedShapesCopy[i];
                    this.selectedShapes[i].Points = shape.Points;
                }
            }

            this.selectedShapesCopy = new List<Shape.FlyShape>();
            this.Invalidate();
            this.StoreShapes();
            return true;
        }



        public void SelectedShapes(List<Shape.FlyShape> shapes)
        {
            this.SetHiding();
            this.selectionChanged?.Invoke(shapes);
            this.Invalidate();
        }


        public void DeSelectecShape()
        {
            if (this.selectedShapes != null && this.selectedShapes.Count > 0)
            {
                this.SetHiding(false);
                this.selectionChanged?.Invoke(new List<Shape.FlyShape>());
                this.hShapeIsSelected = false;
                this.Invalidate();
            }
        }









        ///// <summary>
        ///// 设置编辑状态
        ///// </summary>
        ///// <param name="value">false:创建图形,true:编辑图形</param>
        //public void SetEditing(bool value = true)
        //{
        //    this._isEditMode = !value;
        //    if (!this._isEditMode)
        //    {
        //        // CREATE -> EDIT
        //        //Repaint();
        //    }
        //    else
        //    {
        //        // EDIT -> CREATE
        //        UnHighlight();
        //        DeSelectShape();
        //    }
        //}



        /// <summary>
        /// 设置编辑状态
        /// </summary>
        /// <param name="value">false:创建图形,true:编辑图形</param>
        public void StopDraw()
        {
            this._isEditMode = true;

            // EDIT -> CREATE
            UnHighlight();
            DeSelectShape();

        }




        /// <summary>
        /// 设置为绘图状态
        /// </summary> 
        public void StartDraw(ShapeTypeEnum shapeType)
        {
            this._isEditMode = false;
            this._createMode = shapeType;

            // CREATE -> EDIT
            //Repaint();
        }


        private void Canvas_shapeSelectionChanged(List<FlyShape> selected_shapes)
        {
            //this._noSelectionsSlot = true;
            //this.canvas.selectedShapes.ForEach(shp => shp.Selected = false);
            //this.dgvLabelList.ClearSelection();
            //this.selectedShapes = selected_shapes;
            //this.selectedShapes.ForEach(shape =>
            //{
            //    shape.Selected = true;
            //    foreach (DataGridViewRow row in this.dgvLabelList.Rows)
            //    {
            //        if (row.IsNewRow)
            //        {
            //            continue;
            //        }
            //        if (row.Tag is not ShapeListItemTag listItemTag)
            //        {
            //            continue;
            //        }
            //        if (listItemTag.Shape == shape)
            //        {
            //            row.Selected = true;
            //        }
            //    }
            //});
            //this._noSelectionsSlot = false;

            //bool n_selected = selected_shapes.Count > 0;

            //this.btnDeleteSelectedShape.Enabled = n_selected;
            //this.btnCopySelectedShape.Enabled = n_selected;
            //this.btnEditMode.Enabled = n_selected;

        }



        public void ClearDraw()
        {
            this.OutsideShapes.Clear();
            Invalidate();
        }

        public void DrawCircle(PointF center, float r, float lineWidth = 2)
        {
            FlyShape flyShape = new FlyShape();
            flyShape.Points.Add(center);
            flyShape.Points.Add(new PointF(center.X + r, center.Y));
            flyShape.ShapeType = ShapeTypeEnum.Circle;
            flyShape.line_color = Color.Red;
            flyShape.LineWidth = lineWidth;

            OutsideShapes.Add(flyShape);

            Invalidate();
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="rectWidth"></param>
        public void DrawLine(PointF p1, PointF p2, float rectWidth=0)
        {
            FlyShape shp = new FlyShape();
            shp.Points.Add(p1);
            shp.Points.Add(p2);
            shp.ShapeType = ShapeTypeEnum.Line;
            shp.line_color = Color.Red;
            shp.LineWidth = 2;
            if (rectWidth > 0)
            {
                shp.IsDrawLineVirtualRect = true;
                shp.LineVirtualRectWidth = rectWidth;
            }

            OutsideShapes.Add(shp);

            Invalidate();
        }

        public void DrawRectangle(PointF p1, PointF p2, float rotate)
        {
            FlyShape flyShape = new FlyShape();
            flyShape.Points.Add(p1);
            //flyShape.Points.Add(new PointF(p2.X, p1.Y)); // 改动6
            flyShape.Points.Add(p2);
            //flyShape.Points.Add(new PointF(p1.X, p2.Y)); // 改动6
            flyShape.ShapeType = ShapeTypeEnum.Rectangle;
            flyShape.line_color = Color.Red;
            flyShape.LineWidth = 2;
            flyShape._currentRotateAngle = rotate;

            OutsideShapes.Add(flyShape);

            Invalidate();
        }

    }
}