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