123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- using PaintDotNet.Annotation.Enum;
- using PaintDotNet.Base.CommTool;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- /*
- * 视场,
- * 全部图形构成基于点阵(Points)拟合.
- * 图形变换,对外属性均依赖于点阵的换算.
- * 点阵集合继承DrawObject 的 pointArrayList 字段
- * 全部接口数值皆为原始数值并未进行缩放处理.
- */
- namespace PaintDotNet.Annotation.FieldView
- {
- public abstract class ViewBase : DrawObject
- {
- /// <summary>
- /// 鼠标形状
- /// </summary>
- public static Cursor m_rotateCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationRotateHandle.cur"));
- public static Cursor m_resizeCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationResizeHandle.cur"));
- public override double Width
- {
- get => Rectangle.Width;
- set
- {
- }
- }
- public override double Height
- {
- get => Rectangle.Height;
- set
- {
- }
- }
- #region Points
- public virtual List<PointF> Points
- {
- get
- {
- if (pointArrayList == null)
- pointArrayList = new List<PointF>();
- return pointArrayList;
- }
- set
- {
- pointArrayList = new List<PointF>();
- foreach (var p in value)
- {
- pointArrayList.Add(p);
- }
- }
- }
- public void AddPoint(int x, int y)
- {
- AddPoint(new PointF(x, y));
- }
- protected void AddPoint(PointF point)
- {
- Points.Add(point);
- }
- public override List<PointF> GetPoints()
- {
- return Points;
- }
- #endregion
- #region Bounding Rectangle
- public override RectangleF Rectangle
- {
- get
- {
- return GetBoundingBox();
- }
- }
- /// <summary>
- /// 外接矩形
- /// </summary>
- public override RectangleF GetBoundingBox()
- {
- float minx = 0, maxx = 0, miny = 0, maxy = 0;
- for (int i = 0; i < Points.Count; i++)
- {
- if (i == 0)
- {
- minx = maxx = Points[i].X;
- miny = maxy = Points[i].Y;
- }
- else
- {
- if (Points[i].X > maxx) maxx = Points[i].X;
- if (Points[i].X < minx) minx = Points[i].X;
- if (Points[i].Y > maxy) maxy = Points[i].Y;
- if (Points[i].Y < miny) miny = Points[i].Y;
- }
- }
- return new RectangleF(minx, miny, maxx - minx, maxy - miny);
- }
- #endregion
- #region Draw
- /// <summary>
- /// 指定如何组合不同的剪辑区域
- /// 用于存储是合并视场、还是剪切视场
- /// </summary>
- public CombineMode combineMode;
- /// <summary>
- /// Draw rectangle
- /// </summary>
- /// <param name="g"></param>
- public override void Draw(Graphics g)
- {
- Region reg = g.Clip;
- ViewBase view = null;
- for (int i = ISurfaceBox.GraphicsList.Count - 1; ;)
- {
- if (ISurfaceBox.GraphicsList[i].objectType == DrawClass.View)
- {
- view = (ViewBase)ISurfaceBox.GraphicsList[i];
- if (view.combineMode == CombineMode.Union)
- {
- break;
- }
- }
- i--;
- if (i < 0)
- {
- view.combineMode = CombineMode.Union;
- break;
- }
- }
- //获取所有合并的视场
- Region union = GetUnionOrDeleteView(CombineMode.Union);
- //获取所有删除的视场
- Region delete = GetUnionOrDeleteView(CombineMode.Complement);
- if (union != null)
- {
- reg.Xor(union);
- }
- if (delete != null)
- {
- reg.Union(delete);
- }
- SolidBrush sb = new SolidBrush(Color.FromArgb(180, 0, 0, 0));
- g.FillRegion(sb, reg);
- }
- /// <summary>
- /// 获取所有合并或删除的视场
- /// </summary>
- /// <returns></returns>
- private Region GetUnionOrDeleteView(CombineMode combineMode)
- {
- Region region = null;
- if (ISurfaceBox.GraphicsList != null && ISurfaceBox.GraphicsList.Count > 0)
- {
- for (int i = 0; i < ISurfaceBox.GraphicsList.Count; i++)
- {
- if (ISurfaceBox.GraphicsList[i].objectType == DrawClass.View)
- {
- ViewBase view = (ViewBase)ISurfaceBox.GraphicsList[i];
- GraphicsPath path = new GraphicsPath();
- switch (view.drawToolType)
- {
- case DrawToolType.ViewOval:
- path.AddClosedCurve(ISurfaceBox.GraphicsList[i].GetPoints().ToArray());
- break;
- case DrawToolType.ViewCircle:
- path.AddEllipse(ISurfaceBox.GraphicsList[i].Rectangle);
- break;
- case DrawToolType.ViewSquare:
- case DrawToolType.ViewRectangle:
- case DrawToolType.ViewTriangle:
- case DrawToolType.ViewPolygon:
- case DrawToolType.ViewTriangleEx:
- case DrawToolType.ViewRectangleEx:
- if ((ISurfaceBox.GraphicsList[i]).GetPoints().Count > 2)
- {
- path.AddPolygon((ISurfaceBox.GraphicsList[i]).GetPoints().ToArray());
- }
- break;
- }
- if (view.combineMode == combineMode)
- {
- if (region == null)
- region = new Region(path);
- else
- region.Union(path);
- }
- }
- }
- }
- return region;
- }
- public override void DrawTracker(Graphics g)
- {
- if (!Selected)
- return;
- SolidBrush brush = new SolidBrush(Color.FromArgb(184, Color.Black));
- var pen = new Pen(Color.FromArgb(0, 148, 255));
- switch (drawToolType)
- {
- case DrawToolType.ViewOval:
- g.DrawClosedCurve(pen, GetPoints().ToArray());
- break;
- case DrawToolType.ViewCircle:
- g.DrawEllipse(pen, Rectangle);
- break;
- case DrawToolType.ViewSquare:
- case DrawToolType.ViewRectangle:
- case DrawToolType.ViewTriangle:
- case DrawToolType.ViewPolygon:
- case DrawToolType.ViewTriangleEx:
- case DrawToolType.ViewRectangleEx:
- if (GetPoints().Count > 2)
- {
- g.DrawPolygon(pen, GetPoints().ToArray());
- }
- break;
- }
- if (Rotatable && Points.Count > 2)
- {
- for (int i = 1; i <= HandleCount - 1; i++)
- {
- g.FillRectangle(brush, GetHandleRectangle(i));
- g.DrawRectangle(pen, GetHandleRectangle(i));
- }
- brush = new SolidBrush(Color.Red);
- g.FillEllipse(brush, GetHandleRectangle(HandleCount));
- brush.Dispose();
- }
- else
- {
- for (int i = 1; i <= HandleCount; i++)
- {
- g.FillRectangle(brush, GetHandleRectangle(i));
- g.DrawRectangle(pen, GetHandleRectangle(i));
- }
- }
- }
- #endregion
- #region Rotate
- protected PointF _lastPoint;
- protected PointF _lastCenter;
- protected bool _isRotating;
- /// <summary>
- /// 设置可旋转性,用于显示旋转Handle
- /// </summary>
- public bool Rotatable = false;
- /// <summary>
- /// 图形斜率,用于旋转
- /// </summary>
- public double K
- {
- get;
- set;
- } = 0;
- public virtual void SetK() { }
- public virtual PointF Center
- {
- get
- {
- var centerX = Rectangle.X + Math.Abs(Rectangle.Width / 2);
- var centerY = Rectangle.Y + Math.Abs(Rectangle.Height / 2);
- return new PointF(centerX, centerY);
- }
- set { }
- }
- protected virtual void StartRotate()
- {
- _isRotating = true;
- _lastCenter = Center;
- }
- protected virtual void EndRotate()
- {
- _isRotating = false;
- SetK();
- }
- protected virtual void MoveRotate(PointF point)
- {
- if (!_isRotating)
- {
- StartRotate();
- _lastPoint = point;
- }
- double angle = BasicCalculationHelper.CalculateAngle(_lastCenter.X, _lastCenter.Y, _lastPoint.X, _lastPoint.Y, point.X, point.Y);
- _lastPoint = point;
- for (int i = 0; i < Points.Count; i++)
- {
- Points[i] = BasicCalculationHelper.GetAnglePoint(Points[i], _lastCenter, angle);
- }
- }
- /// <summary>
- /// 标准化外接矩形
- /// </summary>
- public override void Normalize()
- {
- Console.WriteLine("Normalize");
- if (_isRotating)
- EndRotate();
- }
- #endregion
- #region Select
- /// <summary>
- /// Hit test.
- /// Return value: -1 - no hit
- /// 0 - hit anywhere
- /// > 1 - handle number
- /// </summary>
- /// <param name="pointscroll"></param>
- /// <returns></returns>
- public override int HitTest(Point point)
- {
- if (Selected)
- {
- for (int i = 1; i <= HandleCount; i++)
- {
- if (GetHandleRectangle(i).Contains(point))
- return i;
- }
- }
- if (PointInObject(point))
- return 0;
- return -1;
- }
- protected override bool PointInObject(Point point)
- {
- int counter = 0;
- int i;
- double xinters;
- PointF p1, p2;
- int pointCount = Points.Count;
- p1 = Points[0];
- for (i = 1; i <= pointCount; i++)
- {
- p2 = Points[i % pointCount];
- if (point.Y > Math.Min(p1.Y, p2.Y)//校验点的Y大于线段端点的最小Y
- && point.Y <= Math.Max(p1.Y, p2.Y))//校验点的Y小于线段端点的最大Y
- {
- if (point.X <= Math.Max(p1.X, p2.X))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断).
- {
- if (p1.Y != p2.Y)//线段不平行于X轴
- {
- xinters = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
- if (p1.X == p2.X || point.X <= xinters)
- {
- counter++;
- }
- }
- }
- }
- p1 = p2;
- }
- return counter % 2 != 0;
- }
- public override bool IntersectsWith(Rectangle rectangle)
- {
- return Rectangle.IntersectsWith(rectangle);
- }
- #endregion
- public override void Move(int x, int y)
- {
- for (int i = 0; i < Points.Count; i++)
- {
- PointF p = Points[i];
- p.X += x;
- p.Y += y;
- Points[i] = p;
- }
- OnPropertyChanged();
- }
- /// <summary>
- /// 获取视场面积
- /// </summary>
- /// <returns></returns>
- public virtual double Getacreage()
- {
- var count = Points.Count;
- double area0 = 0;
- double area1 = 0;
- for (int i = 0; i < count; i++)
- {
- var x = Points[i].X;
- var y = i + 1 < count ? Points[i + 1].Y : Points[0].Y;
- area0 += x * y;
- x = Points[i].Y;
- y = i + 1 < count ? Points[i + 1].X : Points[0].X;
- area1 += x * y;
- }
- return Math.Abs(0.5 * (area0 - area1));
- }
- }
- }
|