using Io.Github.Kerwinxu.LibShapes.Core.Serialize;
using Io.Github.Kerwinxu.LibShapes.Core.Shape;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
namespace Io.Github.Kerwinxu.LibShapes.Core
{
///
/// 图形的集合
///
public class Shapes
{
#region 保存读取相关
private static ISerialize serialize = new JsonSerialize();
///
/// 读取
///
///
///
public static Shapes load(string filename)
{
if (serialize != null
&& ! string.IsNullOrEmpty(filename)
&& System.IO.File.Exists(filename))
{
return serialize.DeserializeObject(System.IO.File.ReadAllText(filename));
}
else
{
return null;
}
}
///
/// 写入
///
///
public void save(string filename)
{
// 写入文件
if (serialize != null)
{
System.IO.File.WriteAllText(filename, serialize.SerializeObject(this));
}
}
#endregion
#region 一堆属性,这些可以被json保存
// 图形的集合
public List lstShapes { get; set; }
///
/// 坐标转换
///
public PointTransform pointTransform { get; set; }
///
/// 纸张的信息
///
public Paper.Paper Paper { get; set; }
///
/// 变量信息
///
private Dictionary _vars;
public Dictionary Vars
{
get { return _vars; }
set {
_vars = value;
// 然后这里直接更新吧。
if (value != null && lstShapes != null && lstShapes.Count > 0)
{
foreach (var item in lstShapes)
{
item.setVals(value);
}
}
}
}
#endregion
#region 构造函数
public Shapes()
{
lstShapes = new List();
pointTransform = new PointTransform();
//Paper = new Paper.Paper();
Vars = new Dictionary();
}
#endregion
#region 一堆方法
///
///
///
///
/// 偏移和放大
/// 是否打印模板背景
public void Draw(Graphics g, Matrix matrix, bool isShowModelBackground=true)
{
// 1. 先初始化
initGraphics(g);
// 2. 绘制模板背景
if (isShowModelBackground && this.Paper != null && this.Paper.ModelShape != null)
{
// 这个纸张的绘制,x,y都是0,width和height是模板的宽和高,不是纸张的。
this.Paper.ModelShape.X = 0;
this.Paper.ModelShape.Y = 0;
this.Paper.ModelShape.Draw(g, matrix);
}
// 3. 显示所有的图形。
if (lstShapes != null && lstShapes.Count > 0)
{
foreach (var item in lstShapes)
{
item.Draw(g, matrix); // 绘图每一个
}
}
}
///
/// 这个返回偏移和放大后的矩阵
///
///
public Matrix GetMatrix()
{
return pointTransform.GetMatrix();
}
///
/// 这个主要是用来初始化的,高精度的
///
///
private void initGraphics(Graphics g)
{
g.SmoothingMode = SmoothingMode.HighQuality; // 高质量
g.PixelOffsetMode = PixelOffsetMode.HighQuality; // 指定高质量、低速度呈现。
g.PageUnit = GraphicsUnit.Millimeter; //将毫米设置为度量单位
}
///
/// 鼠标单机选择一个形状
///
///
///
public ShapeEle getSelectShape(PointF pointF)
{
if (lstShapes != null && lstShapes.Count > 0)
{
foreach (var shape in lstShapes)
{
if (shape.IsFill)
{
if (shape.isVisible(pointTransform.GetMatrix(), pointF))
{
return shape;
}
}
else
{
if (shape.isOutlineVisible(pointTransform.GetMatrix(), pointF))
{
return shape;
}
}
}
}
return null;
}
///
/// 选择矩形框内的形状
///
///
///
public List getSelectShapes(RectangleF rect)
{
var matrix = pointTransform.GetMatrix();
if (lstShapes!= null && lstShapes.Count > 0)
{
return lstShapes.Where(x => x.isBeContains(matrix, rect)).ToList();
}
return null;
}
public int getNextId()
{
// 首先取得所有的id
var ids = getIds(this.lstShapes);
if (ids.Count == 0)
{
return 1;
}
int i = ids.Max() + 1;
while (ids.Contains(i))
{
i++; // 不重复的,
}
return i; // 这里简单一点。
}
///
/// 取得所有的id
///
///
///
private ListgetIds(List shapeeles)
{
List ids = shapeeles.Where(x => !(x is ShapeGroup)).Select(x => x.ID).ToList();
foreach (var item in shapeeles.Where(x => x is ShapeGroup))
{
ids.AddRange(getIds(((ShapeGroup)item).shapes));
}
return ids;
}
///
/// 根据某个id取得相应的形状。
///
///
///
public ShapeEle getShape(int id)
{
return getShape(lstShapes, id);
}
private ShapeEle getShape(List shapeeles, int id)
{
if (shapeeles!=null)
{
foreach (var item in shapeeles)
{
if (item.ID == id)
{
return item;
}
if (item is ShapeGroup) // 如果是群组
{
var tmp = getShape(((ShapeGroup)item).shapes,id);
if (tmp != null) return tmp;
}
}
}
return null;
}
///
/// 将这个id的形状替换了。
///
///
///
public void replaceShape(int id, ShapeEle shape)
{
replaceShape(lstShapes, id, shape);
}
private void replaceShape(List shapeeles, int id, ShapeEle shape)
{
// 遍历所有的形状
for (int i = 0; i < shapeeles.Count; i++)
{
if (shapeeles[i] is ShapeGroup)
{
replaceShape(((ShapeGroup)shapeeles[i]).shapes, id, shape);
}
if (shapeeles[i].ID == id)
{
// 找到了
shapeeles.RemoveAt(i);
shapeeles.Insert(i, shape);
return;
}
}
}
///
/// 这个是缩放到指定的大小。
///
///
///
/// 像素宽度
/// 像素高度
/// 像素间距
public void zoomTo(float dpix, float dpiy, float width, float height, float spacing)
{
// 然后计算放大
var width2 = (width - spacing * 2) / dpix * 25.4; // 转成mm
var height2 = (height - spacing * 2) / dpiy * 25.4; // 转成mm
// 然后计算所有图形的的宽度和高度
ShapeGroup group = new ShapeGroup();
group.shapes = lstShapes.Select(x => x).ToList();// 这里用复制的方式
// 这里要判断是否有纸张
if (this.Paper != null && this.Paper.ModelShape != null)
{
group.shapes.Add(this.Paper.ModelShape);
}
// 如果没有图形,就直接退出
if (group.shapes.Count == 0) return;
//
var rect = group.GetBounds(new Matrix());// 取得不存在放大偏移的情况下,这个的尺寸
// 这里解方程,思路是,画布的宽度=倍数*(形状总宽度+两边间距的宽度)
//width/dpix*25.4 = zoom * (rect.Width + spacing*2/dpix*25.4 /zoom)
// width/dpix*25.4 = zoom * (rect.Width + spacing*2/dpix*25.4
var scale1 = (width / dpix * 25.4f - spacing * 2 / dpix * 25.4f) / rect.Width;
var scale2 = (height / dpiy * 25.4f - spacing * 2 / dpiy * 25.4f) / rect.Height;
// 取得较小值
this.pointTransform.Zoom = scale1 < scale2 ? scale1 : scale2; // 取得较小值。
// 然后这里有一个偏移,要算正负两个方向的偏移,要流出两边的spacing,主要留出左边和上边就可以了。
this.pointTransform.OffsetX = - rect.X + spacing / dpix * 25.4f ;
this.pointTransform.OffsetY = - rect.Y + spacing / dpix * 25.4f ;
}
///
/// 深度复制一个
///
///
public Shapes DeepClone()
{
//这里用json的方式
JsonSerialize jsonSerialize = new JsonSerialize();
string json = jsonSerialize.SerializeObject(this);
// 可能原因是存在自定义对象的集合,所以这里要用复杂的方式去做
return jsonSerialize.DeserializeObject(json);
}
#endregion
}
}