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