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
{
///
/// 鼠标形状
///
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 Points
{
get
{
if (pointArrayList == null)
pointArrayList = new List();
return pointArrayList;
}
set
{
pointArrayList = new List();
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 GetPoints()
{
return Points;
}
#endregion
#region Bounding Rectangle
public override RectangleF Rectangle
{
get
{
return GetBoundingBox();
}
}
///
/// 外接矩形
///
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
///
/// 指定如何组合不同的剪辑区域
/// 用于存储是合并视场、还是剪切视场
///
public CombineMode combineMode;
///
/// Draw rectangle
///
///
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);
}
///
/// 获取所有合并或删除的视场
///
///
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;
///
/// 设置可旋转性,用于显示旋转Handle
///
public bool Rotatable = false;
///
/// 图形斜率,用于旋转
///
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);
}
}
///
/// 标准化外接矩形
///
public override void Normalize()
{
Console.WriteLine("Normalize");
if (_isRotating)
EndRotate();
}
#endregion
#region Select
///
/// Hit test.
/// Return value: -1 - no hit
/// 0 - hit anywhere
/// > 1 - handle number
///
///
///
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();
}
///
/// 获取视场面积
///
///
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));
}
}
}