using PaintDotNet.Annotation.Enum; using PaintDotNet.Base.CommTool; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; using System.Runtime.Serialization; using System.Windows.Forms; namespace PaintDotNet.Annotation.FieldView { /// /// 椭圆形视场绘制 /// public class ViewOval : ViewBase { #region Calculate List> m_ovalTemple; float _a; float _b; float _centerx; float _centery; float _angle = 0; readonly float _sqrt2 = (float)Math.Sqrt(2); public override double Width { get => _a * 2; set { _a = (float)value / 2; _centerx = Center.X; _centery = Center.Y; Points = CalculateCirclePoints(); } } public override double Height { get => _b * 2; set { _b = (float)value / 2; _centerx = Center.X; _centery = Center.Y; Points = CalculateCirclePoints(); } } void InitOvalTemplate() { m_ovalTemple = new List>(); m_ovalTemple.Add( new Func(() => { return new PointF(-(_a / _sqrt2), -(_b / _sqrt2)); })); m_ovalTemple.Add( new Func(() => { return new PointF(0, -_b); })); m_ovalTemple.Add( new Func(() => { return new PointF((_a / _sqrt2), -(_b / _sqrt2)); })); m_ovalTemple.Add( new Func(() => { return new PointF(_a, 0); })); m_ovalTemple.Add( new Func(() => { return new PointF((_a / _sqrt2), (_b / _sqrt2)); })); m_ovalTemple.Add( new Func(() => { return new PointF(0, _b); })); m_ovalTemple.Add( new Func(() => { return new PointF(-(_a / _sqrt2), (_b / _sqrt2)); })); m_ovalTemple.Add( new Func(() => { return new PointF(-_a, 0); })); } List CalculateCirclePoints() { List points = new List(); foreach (var func in m_ovalTemple) { var p = func.Invoke(); p = BasicCalculationHelper.GetAnglePoint(p, _lastCenter, _angle); points.Add(new PointF(p.X + _centerx, p.Y + _centery)); } return points; } /// /// 当PointList被修改时,更新参数 /// /// void ReverseBuild(List points) { _b = (float)(BasicCalculationHelper.GetDistance(points[1], points[5]) / 2); _a = (float)(BasicCalculationHelper.GetDistance(points[3], points[7]) / 2); _centerx = (points[1].X + points[5].X) / 2; _centery = (points[1].Y + points[5].Y) / 2; _angle = (float)BasicCalculationHelper.CalculateAngle(new PointF(_centerx, _centery), new PointF(_centerx + 100, _centery), points[3]); } public override double Getacreage() { var b = BasicCalculationHelper.GetDistance(Points[1], Points[5]) / 2; var a = BasicCalculationHelper.GetDistance(Points[3], Points[7]) / 2; return Math.PI * a * b; } #endregion #region Constructor public ViewOval() { this.objectType = DrawClass.View; this.drawToolType = DrawToolType.ViewOval; Rotatable = true; Initialize(); InitOvalTemplate(); } public ViewOval(int x, int y) : this() { for (int i = 0; i < 8; i++) AddPoint(x, y); } public ViewOval(List points) : this() { ReverseBuild(points); Points = points; } #endregion public override PointF Center { get { var x = (Points[1].X + Points[5].X) / 2; var y = (Points[1].Y + Points[5].Y) / 2; return new PointF(x, y); } set { } } #region Handle public override int HandleCount => 9; public override PointF GetHandle(int handleNumber) { if (handleNumber > Points.Count) { var x = (Center.X + Points[3].X) / 2; var y = (Center.Y + Points[3].Y) / 2; return new PointF(x, y); } else return Points[handleNumber - 1]; } public override Cursor GetHandleCursor(int handleNumber) { switch (handleNumber) { case 9: return m_rotateCursor; default: return m_resizeCursor; } } public override void MoveHandleTo(Point point, int handleNumber) { if (handleNumber == 9) MoveRotate(point); else if (handleNumber % 2 != 0) MoveCorner(point); else MoveEdage(point, handleNumber); OnPropertyChanged(); } private void MoveCorner(Point point) { _centerx = Center.X; _centery = Center.Y; var p = BasicCalculationHelper.GetAnglePoint(point, new PointF(_centerx, _centery), -_angle); _a = Math.Abs(p.X - Center.X) * _sqrt2; _b = Math.Abs(p.Y - Center.Y) * _sqrt2; Points = CalculateCirclePoints(); } protected override void MoveRotate(PointF point) { _centerx = Center.X; _centery = Center.Y; _angle = (float)BasicCalculationHelper.CalculateAngle(new PointF(_centerx, _centery), new PointF(_centerx + 100, _centery), point); Points = CalculateCirclePoints(); } private void MoveEdage(Point point, int i) { var o = Points[(i + 3) % 8]; var p = BasicCalculationHelper.GetAnglePoint(point, o, -_angle); var c = BasicCalculationHelper.GetAnglePoint(Center, o, -_angle); if (i % 4 == 0) { c.X = (p.X + o.X) / 2; _a = Math.Abs(p.X - o.X) / 2; } else { c.Y = (p.Y + o.Y) / 2; _b = Math.Abs(p.Y - o.Y) / 2; } c = BasicCalculationHelper.GetAnglePoint(c, o, _angle); _centerx = c.X; _centery = c.Y; Points = CalculateCirclePoints(); } #endregion #region Clone public override DrawObject Clone() { return Clone(ISurfaceBox); } public override DrawObject Clone(ISurfaceBox surfaceBox) { ViewOval drawRectangle = new ViewOval(Points); drawRectangle.ISurfaceBox = surfaceBox; drawRectangle.combineMode = this.combineMode; drawRectangle.Color = Color; drawRectangle.ID = ID; FillDrawObjectFields(drawRectangle); return drawRectangle; } #endregion } }