358 lines
10 KiB
C#
358 lines
10 KiB
C#
using Io.Github.Kerwinxu.LibShapes.Utils;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Io.Github.Kerwinxu.LibShapes.Core.Shape
|
|
{
|
|
/// <summary>
|
|
/// 形状的基类
|
|
/// </summary>
|
|
public abstract class ShapeEle
|
|
{
|
|
|
|
/// <summary>
|
|
/// 构造函数
|
|
/// </summary>
|
|
public ShapeEle()
|
|
{
|
|
// 提供一些默认的参数
|
|
PenWidth = 1;
|
|
PenColor = Color.Black;
|
|
|
|
}
|
|
|
|
|
|
#region 一堆属性
|
|
#region 设计
|
|
/// <summary>
|
|
/// 唯一的标识符
|
|
/// </summary>
|
|
[CategoryAttribute("设计")]
|
|
public int ID { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region 布局
|
|
|
|
[CategoryAttribute("布局")]
|
|
public float X { get; set; }
|
|
|
|
[CategoryAttribute("布局")]
|
|
public float Y { get; set; }
|
|
|
|
[DescriptionAttribute("宽度"), DisplayName("宽度"), CategoryAttribute("布局")]
|
|
public float Width { get; set; }
|
|
|
|
[DescriptionAttribute("高度"), DisplayName("高度"), CategoryAttribute("布局")]
|
|
public float Height { get; set; }
|
|
|
|
[DescriptionAttribute("角度"), DisplayName("角度"), CategoryAttribute("外观")]
|
|
public float Angle { get; set; }
|
|
|
|
|
|
#endregion
|
|
|
|
#region 外观
|
|
|
|
[DescriptionAttribute("边框颜色"), DisplayName("边框颜色"), CategoryAttribute("外观")]
|
|
public Color PenColor { get; set; }
|
|
|
|
[DescriptionAttribute("边框粗细"), DisplayName("边框粗细"), CategoryAttribute("外观")]
|
|
public float PenWidth { get; set; }
|
|
|
|
[DescriptionAttribute("虚线的样式"), DisplayName("虚线的样式"), CategoryAttribute("外观")]
|
|
public DashStyle PenDashStyle { get; set; }
|
|
|
|
[DescriptionAttribute("是否填充"), DisplayName("是否填充"), CategoryAttribute("外观")]
|
|
public bool IsFill { get; set; }
|
|
|
|
[DescriptionAttribute("填充颜色"), DisplayName("填充颜色"), CategoryAttribute("外观")]
|
|
public Color FillColor { get; set; }
|
|
|
|
|
|
#region 如下的几个是为了更改大小或者移动的时候用的
|
|
float x_add, y_add, width_add, height_add;
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region 操作
|
|
|
|
public virtual void Draw(Graphics g, Matrix matrix) {
|
|
// 首先取得绘图路径
|
|
try
|
|
{
|
|
var path = GetGraphicsPath(matrix);
|
|
// 定义画笔
|
|
Pen pen = new Pen(PenColor);
|
|
pen.Width = PenWidth; // 画笔的粗细
|
|
pen.DashStyle = PenDashStyle; // 虚线的样式
|
|
g.DrawPath(pen, path); // 画边框
|
|
if (IsFill) // 如果填充
|
|
{
|
|
Brush brush = new SolidBrush(FillColor);
|
|
g.FillPath(brush, path);
|
|
}
|
|
path.Dispose();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
//throw;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 这个返回的是屏幕画布上的真实的坐标体系
|
|
/// </summary>
|
|
/// <param name="matrix"></param>
|
|
/// <returns></returns>
|
|
public virtual GraphicsPath GetGraphicsPath(Matrix matrix)
|
|
{
|
|
GraphicsPath path = null;
|
|
if (getWidth() == 0 || getHeight() == 0)
|
|
{
|
|
// 这里表示只是一条线段或者一个点了
|
|
path = new GraphicsPath();
|
|
path.AddLine(new PointF(getX(), getY()), new PointF(getX() + getWidth(), getY() + getHeight()));
|
|
}
|
|
else
|
|
{
|
|
path = GetGraphicsPathWithAngle();
|
|
}
|
|
|
|
// 这里加上旋转
|
|
Matrix matrix1 = new Matrix();
|
|
// 这里按照中心点旋转,
|
|
var rect = path.GetBounds();
|
|
var centerPoint = new PointF() { X = rect.X + rect.Width / 2, Y = rect.Y + rect.Height / 2 };
|
|
matrix1.RotateAt(Angle, centerPoint);
|
|
Matrix matrix2 = matrix.Clone();
|
|
matrix2.Multiply(matrix1);
|
|
// 应用这个转换
|
|
path.Transform(matrix2);
|
|
// 返回这个路径
|
|
return path;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 矫正矩形,宽和高都不能是复数
|
|
/// </summary>
|
|
/// <param name="rect"></param>
|
|
/// <returns></returns>
|
|
protected RectangleF correctRectangle(RectangleF rect)
|
|
{
|
|
RectangleF rect2 = new RectangleF() {
|
|
X = rect.X,
|
|
Y = rect.Y,
|
|
Width = rect.Width,
|
|
Height = rect.Height,
|
|
};
|
|
if (rect2.Width < 0)
|
|
{
|
|
rect2.X += rect2.Width;
|
|
rect2.Width = -rect2.Width;
|
|
}
|
|
if (rect2.Height < 0)
|
|
{
|
|
rect2.Y += rect2.Height;
|
|
rect2.Height = -rect2.Height;
|
|
}
|
|
|
|
return rect2;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回不包括旋转的路径,且这个是虚拟世界的坐标,不用考虑画布中实际的坐标。
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual GraphicsPath GetGraphicsPathWithAngle()
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
var rect = new System.Drawing.RectangleF()
|
|
{
|
|
X = getX(),
|
|
Y = getY(),
|
|
Width = getWidth(),
|
|
Height = getHeight()
|
|
};
|
|
var rect2 = correctRectangle(rect);
|
|
|
|
path.AddRectangle(rect2);
|
|
return path;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回外接矩形
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual RectangleF GetBounds(Matrix matrix)
|
|
{
|
|
// 请注意,这里是以旋转后的。
|
|
return GetGraphicsPath(matrix).GetBounds();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 选择的容忍度
|
|
/// </summary>
|
|
private Pen pen_select_tolerance = new Pen(Color.White) {
|
|
Width = DistanceCalculation.select_tolerance
|
|
};
|
|
|
|
/// <summary>
|
|
/// 这个点是否在这个图形的轮廓上
|
|
/// </summary>
|
|
/// <param name="mousePointF"></param>
|
|
/// <returns></returns>
|
|
public virtual bool isOutlineVisible(Matrix matrix, PointF mousePointF)
|
|
{
|
|
|
|
var pen = new Pen(new SolidBrush(this.PenColor), this.PenWidth);
|
|
return GetGraphicsPath(matrix).IsOutlineVisible(mousePointF, pen);
|
|
|
|
//return GetGraphicsPath(matrix).IsVisible(mousePointF);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 这个点是否在这个图形的的内部
|
|
/// </summary>
|
|
/// <param name="mousePointF"></param>
|
|
/// <returns></returns>
|
|
public virtual bool isVisible(Matrix matrix, PointF mousePointF)
|
|
{
|
|
return GetGraphicsPath(matrix).IsVisible(mousePointF);
|
|
|
|
//return GetGraphicsPath(matrix).IsVisible(mousePointF);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 这个表示是否被包含在这个矩形内
|
|
/// </summary>
|
|
/// <param name="rect"></param>
|
|
/// <returns></returns>
|
|
public virtual bool isBeContains(Matrix matrix, RectangleF rect)
|
|
{
|
|
var rect2 = GetBounds(matrix);
|
|
return rect.Contains(rect2);
|
|
}
|
|
|
|
|
|
|
|
public virtual void setVals(Dictionary<string, string> vars)
|
|
{
|
|
// 什么都不做,子类如果需要,就自己实现。
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据这个矩形更改
|
|
/// </summary>
|
|
/// <param name="rect"></param>
|
|
public void Change(RectangleF rect)
|
|
{
|
|
x_add = rect.X;
|
|
y_add = rect.Y;
|
|
width_add = rect.Width;
|
|
height_add = rect.Height;
|
|
}
|
|
|
|
|
|
public virtual void ChangeComplated()
|
|
{
|
|
// 将更改固定下来
|
|
X += x_add;
|
|
Y += y_add;
|
|
Width += width_add;
|
|
Height += height_add;
|
|
// 清零
|
|
x_add = 0;
|
|
y_add = 0;
|
|
width_add = 0;
|
|
height_add = 0;
|
|
|
|
// 这里要注意矫正 todo
|
|
if (Width < 0)
|
|
{
|
|
X += Width;
|
|
Width = -Width;
|
|
}
|
|
if (Height < 0)
|
|
{
|
|
Y += Height;
|
|
Height = -Height;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 深度拷贝
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <returns></returns>
|
|
public abstract ShapeEle DeepClone();
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
// 首先判断是否是
|
|
|
|
var shape = obj as ShapeEle;
|
|
if (shape == null) return false; // 转换失败就是不同啦
|
|
|
|
return this.X == shape.X &&
|
|
this.Y == shape.Y &&
|
|
this.Width == shape.Width &&
|
|
this.Height == shape.Height &&
|
|
this.Angle == shape.Angle &&
|
|
this.ID == shape.ID &&
|
|
this.PenColor == shape.PenColor &&
|
|
this.PenWidth == shape.PenWidth &&
|
|
this.PenDashStyle == shape.PenDashStyle &&
|
|
this.IsFill == shape.IsFill &&
|
|
this.FillColor == shape.FillColor;
|
|
|
|
//return base.Equals(obj);
|
|
}
|
|
|
|
|
|
#region 如下的几个是添加add后的参数
|
|
protected float getX()
|
|
{
|
|
return X + x_add;
|
|
}
|
|
protected float getY()
|
|
{
|
|
return Y + y_add;
|
|
}
|
|
protected float getWidth()
|
|
{
|
|
return Width + width_add;
|
|
}
|
|
protected float getHeight()
|
|
{
|
|
return Height + height_add;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return ID * base.GetHashCode();
|
|
//return base.GetHashCode();
|
|
}
|
|
}
|
|
}
|