using OTSIncAReportApp.DataOperation.Model; using OTSIncAReportGraph.Class; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace OTSIncAReportGraph { /// /// Particle对象上操作状态的枚举,显示,不显示,已删除,已选择 /// public enum PaintState { NORMALPAINT = 0, NOPAINT = 1, CONCISEPAINT=2,// display as a "+" } public enum DisplayState { DISPLAY = 0, NODISPLAY = 1, } /// /// Particle对象上操作xray的枚举状态,显示xray数据,不显示 /// public enum ParticleShowXray { SELECTANDDISPLAYXRAY = 0, NODISPLAY = 1, } /// /// Segment对象绘制的枚举,以点绘制,还是以线绘制 /// public enum SegmentShowMode { DRAWPOINT = 0, DRAWLINE = 1, } /// /// 颗粒类 /// public class DisplayParticle : BaseObject, ICloneable, IComparable { private const float m_zoom_displaymultiplier = 0.5f; public Particle objParticleData; private Guid m_id; private RectangleF m_rect; private PointF m_OTSPointF; private RectangleF m_small_rect; private bool m_isSelected_smallrect; private bool m_showSmallx; private bool m_isSelected; private bool m_isDeleted; private bool m_isMouseOver; private PaintState m_paintState = PaintState.NORMALPAINT; private ParticleShowXray m_operator_showxray = ParticleShowXray.NODISPLAY;//选定显示XRAY,不显示XRAY,默认应为(不显示XRAY) private bool m_isdragging; private PointF m_dragingpoint; private Color m_color; private Color m_backcolor; private GraphicsPath m_gpath; private List m_listdsegment = new List(); private DisplayState m_displayState; private string m_sort_type = "从大到小"; private float m_f_size = 0; private string m_str_lj = "颗粒粒级"; private string m_str_klzl = "颗粒种类"; private string m_str_klfl = "颗粒分类"; public int TypeId { get { return objParticleData.TypeId; } } //TypeName public string TypeName { get { return objParticleData.TypeName; } } //XRayId public int XRayId { get { return objParticleData.XrayId; } } public int SEMPosX { get { return objParticleData.SEMPosX; } } public int SEMPosY { get { return objParticleData.SEMPosY; } } public DisplayParticle() { m_id = System.Guid.NewGuid(); } public DisplayParticle(Particle part) { m_id = System.Guid.NewGuid(); objParticleData = part; this.Color = GetColorBySTDTypeIDForBSEAndSorImage(part.TypeColor, part.TypeId); } public DisplayParticle(List in_list_segment, DisplayParticle in_particle) { objParticleData = in_particle.objParticleData; m_id = in_particle.m_id; m_paintState = in_particle.m_paintState; m_operator_showxray = in_particle.m_operator_showxray; foreach (DisplaySegment e in in_list_segment) { m_listdsegment.Add(e.Clone() as DisplaySegment); } } /// /// [目前也不使用该方法了,因为该方法每次排序都有不同的结果]多边形排序,按传入的sort_type的排序类型行排序,但需要两个list做一致性排序 /// /// /// public int CompareTo(DisplayParticle in_particle) { int r_b = 0;//排序返回值 switch (m_sort_type) { case "从大到小": r_b = in_particle.m_f_size.CompareTo(this.m_f_size); break; case "从小到大": //与上面的从大到小正好相反即可 r_b = in_particle.m_f_size.CompareTo(this.m_f_size); if (r_b == 1) r_b = -1; else r_b = 1; break; default: break; } return r_b; } public Color GetColorBySTDTypeIDForBSEAndSorImage(string in_partcolor, int in_stdtypeid) { Color ret_c = new Color(); if (in_stdtypeid < 1000) { ret_c = GetColorByEnum(in_stdtypeid); } else if (in_stdtypeid >= 1000) { //大于等于1000,并且小于10000时,使用用户标准库来分析夹杂物名称 if (!in_partcolor.Contains("#")) { ret_c = DrawFunction.colorHx16toRGB("#" + in_partcolor);//接收必须是#000000的格式 } else { ret_c = DrawFunction.colorHx16toRGB(in_partcolor);//接收必须是#000000的格式 } } return ret_c; } public Color GetColorByEnum(int STDID) { Color ret_c = new Color(); switch (STDID) { case -1: //INVALID = -1, //stdName = "无效颗粒"; ret_c = Color.Black; break; case 0: //small = 0; //stdName = "过小颗粒"; ret_c = Color.Black; break; case 1: //OVERSIZE = 1, //stdName = "过大颗粒"; ret_c = Color.Black; break; case 2: //AVE_GRAY_NOT_INRANRE = 2, //stdName = "亮度不在分析范围内的颗粒"; ret_c = Color.Black; break; case 3: //SEARCH_X_RAY = 3, //stdName = "不进行搜索x-ray分析的颗粒"; ret_c = Color.Black; break; case 4: //LOW_COUNT = 4, //stdName = "低x-ray计数颗粒"; ret_c = Color.Black; break; case 5: //NO_INTEREST_ELEMENTS = 5, //stdName = "不含分析元素的颗粒"; ret_c = Color.Black; break; case 6: //ALAYSIS_X_RAY = 6, //stdName = "不进行x-ray分析的颗粒"; ret_c = Color.Black; break; case 7: //NOT_IDENTIFIED = 7, //stdName = "未识别颗粒"; ret_c = Color.Black; break; case 8: //NOT_IDENTIFIED = 8, //stdName = "未识别颗粒"; ret_c = Color.Black; break; case 9: //NOT_IDENTIFIED = 9, //stdName = "未识别颗粒"; ret_c = Color.Black; break; default: ret_c = Color.Black; break; } return ret_c; } /// /// 克隆方法 /// /// public override object Clone() { return new DisplayParticle(this.m_listdsegment, this); } /// /// ID /// public override Guid guid { get { return m_id; } set { m_id = value; } } /// /// 颗粒的外边框大小 /// public override RectangleF Rect { get { return m_rect; } set { m_rect = value; } } /// /// OTSPointF /// public override PointF OTSPointF { get { return m_OTSPointF; } set { m_OTSPointF = value; } } /// /// 颗粒里+号位置的外边框大小 /// public RectangleF SmallRect { get { return m_small_rect; } set { m_small_rect = value; } } /// /// 颗粒是否被选择 /// public override bool IsSelect { get { return m_isSelected; } set { m_isSelected = value; } } /// /// 该颗粒是否被设置成,选中状态 /// public PaintState GetPaintState() { if (GetDisplayState() == DisplayState.NODISPLAY) { m_paintState = PaintState.NOPAINT; } return m_paintState; } /// /// 该颗粒是否被设置成,选中状态 /// public void SetPaintState(PaintState value) { m_paintState = value; } /// /// 是否对该颗粒选定显示X-Ray能谱图 /// public ParticleShowXray Operator_ShowXRay { get { return m_operator_showxray; } set { m_operator_showxray = value; } } /// /// 是否显示x号 /// public bool IsShowSmallX { get { return m_showSmallx; } set { m_showSmallx = value; } } /// /// 颗粒的x-ray的点,是否被选择上了 /// public bool IsSelectedSmallRect { get { return m_isSelected_smallrect; } set { m_isSelected_smallrect = value; } } /// /// 是否在被拖动 /// public override bool IsDragging { get { return m_isdragging; } set { m_isdragging = value; } } /// /// 被拖动到的位置坐标 /// public override PointF DraggingPoint { get { return m_dragingpoint; } set { m_dragingpoint = value; } } /// /// 线的颜色 /// public override Color Color { get { return m_color; } set { m_color = value; } } /// /// 背景色 /// public override Color BackColor { get { return m_backcolor; } set { m_backcolor = value; } } /// /// 多边形的图形路径边缘 /// public override GraphicsPath GPath { get { return m_gpath; } set { m_gpath = value; } } /// /// 里面包含的多个线的集合 /// public List DSegments { get { return m_listdsegment; } set { m_listdsegment = value; } } /// /// 控制多边形在进行缩放到多少倍时进行显示 /// public float Zoom_DisPlayThreshold { get { return m_zoom_displaymultiplier; } } /// /// 设置排序的类型 /// public string SortType { get { return m_sort_type; } set { m_sort_type = value; } } /// /// 设置该多边形的尺寸大小 /// public float FSize { get { return m_f_size; } set { m_f_size = value; } } /// /// 设置粒级 /// public string ParticleLJ { get { return m_str_lj; } set { m_str_lj = value; } } /// /// 设置种类 /// public string ParticleZL { get { return m_str_klzl; } set { m_str_klzl = value; } } /// /// 设置分类 /// public string ParticleFL { get { return m_str_klfl; } set { m_str_klfl = value; } } /// /// 获取或设置该Particle对应底层的FieldID值 /// public int FieldId { get { return objParticleData.FieldId; } } /// /// 获取或设置该Particle对应底层的ParticleID值 /// public int ParticleId { get { return objParticleData.ParticleId; } } public bool IsDeleted { get => m_isDeleted; set => m_isDeleted = value; } public bool IsMouseOver { get => m_isMouseOver; set => m_isMouseOver = value; } public DisplayState GetDisplayState() { if (m_isDeleted) { m_displayState = DisplayState.NODISPLAY; } return m_displayState; } public void SetDisplayState(DisplayState value) { m_displayState = value; } /// /// 绘制函数 /// /// public override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; //绘制鼠标移动到颗粒上时的边框,需要判断当前鼠标在颗粒上,及颗粒的操作为正常显示 if (m_isMouseOver == true) { //如果有鼠标在该矩形上,那么进行描边 ControlPaint.DrawBorder(g, Rectangle.Round(this.Rect), Color.Lime, 1, ButtonBorderStyle.Solid, Color.Lime, 1, ButtonBorderStyle.Solid, Color.Lime, 1, ButtonBorderStyle.Solid, Color.Lime, 1, ButtonBorderStyle.Solid); } if (GetPaintState() == PaintState.NORMALPAINT) { //调用绘制基本线 foreach (DisplaySegment item in m_listdsegment) { item.OnPaint(e); } } if (GetPaintState() == PaintState.CONCISEPAINT) { g.DrawString("+", new Font("黑体", 6), new SolidBrush(Color.DarkSlateBlue), new PointF(m_small_rect.X, m_small_rect.Y)); } if (m_isSelected) { //如果説该矩形被选择上了的话,那么也显示边框 ControlPaint.DrawBorder(g, Rectangle.Round(this.Rect), Color.Blue, 1, ButtonBorderStyle.Solid, Color.Blue, 1, ButtonBorderStyle.Solid, Color.Blue, 1, ButtonBorderStyle.Solid, Color.Blue, 1, ButtonBorderStyle.Solid); } if (ParticleShowXray.SELECTANDDISPLAYXRAY == m_operator_showxray && PaintState.NOPAINT != GetPaintState()) { //当鼠标在该颗粒上进行点击,则对颗粒状态更改为选定状态,用来显示X-ray能谱表 ControlPaint.DrawBorder(g, Rectangle.Round(this.Rect), Color.DeepSkyBlue, 1, ButtonBorderStyle.Solid, Color.DeepSkyBlue, 1, ButtonBorderStyle.Solid, Color.DeepSkyBlue, 1, ButtonBorderStyle.Solid, Color.DeepSkyBlue, 1, ButtonBorderStyle.Solid); } } /// /// 从Line中获取矩形的边缘闭合路径 /// /// public GraphicsPath GetRegionFromDSegments() { GraphicsPath gpath = new GraphicsPath(); List list_leftpointf = new List(); List list_rightpointf = new List(); //从y循环,这里假设y轴会按lines集合来计算,然后将所有的左x,和右x取出排成两个队列 foreach (DisplaySegment ds in this.m_listdsegment) { list_leftpointf.Add(new PointF(ds.Rect.X, ds.Rect.Y)); list_rightpointf.Add(new PointF(ds.Rect.X + ds.Rect.Width, ds.Rect.Y)); } PointF[] lsp = new PointF[list_leftpointf.Count + list_rightpointf.Count]; //再将两个x,y点依次添加到闭合路径中 for (int i = 0; i < list_leftpointf.Count(); i++) { lsp[i] = list_leftpointf[i]; } //右节点 for (int i = 0; i < list_rightpointf.Count(); i++) { //这边倒着存入 lsp[list_rightpointf.Count() + i] = list_rightpointf[list_rightpointf.Count() - i - 1]; } //防止从低层拿到无数据的外边路径,在我的程序里却需要计算,而防止程序报死,这里做一下特殊处理。 if (lsp.Count() >= 3) { gpath.AddPolygon(lsp); } else { //有时居然有颗粒,有没有segment的时候,防止报错 if (this.DSegments.Count == 0) { lsp = new PointF[3] { new PointF(0, 0), new PointF(0, 0), new PointF(0, 0) }; gpath.AddPolygon(lsp); return gpath; } //有2条数据 if (lsp[1].X != 0 && lsp[1].Y != 0) { lsp = new PointF[3] { new PointF(lsp[0].X, lsp[0].Y), new PointF(lsp[1].X, lsp[1].Y), new PointF(lsp[1].X, lsp[1].Y) }; } //有1条数据 else if (lsp[0].X != 0 && lsp[0].Y != 0) { lsp = new PointF[3] { new PointF(lsp[0].X, lsp[0].Y), new PointF(lsp[0].X, lsp[0].Y), new PointF(lsp[0].X, lsp[0].Y) }; } //剩下的情况 else { lsp = new PointF[3] { new PointF(0, 0), new PointF(0, 0), new PointF(0,0) }; } gpath.AddPolygon(lsp); } return gpath; } /// /// 从已经确定的外边框来计算出里面的+号小框位置 /// /// public RectangleF GetSmallRectangleFromRect() { RectangleF rect = new RectangleF(); //用外边框的坐标,除2获得中心点,然后再分别+,- 4 float x = 0, y = 0; x = m_rect.X + (m_rect.Width / 2); y = m_rect.Y + (m_rect.Height / 2); rect.X = x - 4; rect.Y = y - 4; rect.Width = 8; rect.Height = 4; return rect; } /// /// 根据该多边形所有包含的线长度,计算出,该多边形的面积大小 /// /// public float GetAreaFormSegments() { float f_size_sum = 0; foreach (DisplaySegment ls_ds in this.m_listdsegment) { f_size_sum = f_size_sum + ls_ds.Rect.Width; } return f_size_sum; } /// /// 从基本线中获取整个矩形的Rectangle /// /// public RectangleF GetRectFromDSegment() { RectangleF rect = new RectangleF(); float x1 = 0, y1 = 0; float i_width = 0, i_height = 0; //先从自身中初始化x,y,和宽,高 if (this.m_listdsegment.Count > 0) { x1 = this.m_listdsegment[0].Rect.X; y1 = this.m_listdsegment[0].Rect.Y; i_width = x1 + this.m_listdsegment[0].Rect.Width; i_height = this.m_listdsegment[0].Rect.Y; } foreach (DisplaySegment ds in this.m_listdsegment) { //分别取出,最小的x,y, if (ds.Rect.X < x1) { x1 = ds.Rect.X; } if (ds.Rect.Y < y1) { y1 = ds.Rect.Y; } //最大的x,y if (ds.Rect.X + ds.Rect.Width > i_width) { i_width = ds.Rect.X + ds.Rect.Width; } if (ds.Rect.Y > i_height) { i_height = ds.Rect.Y; } } //对矩形Rect大小位置进行修补,因为画线是内边框,并且计算出来的位置也是向内占用一像素的, //正常应该是 +2,但实际效果,+3也才勉强够用,因为放大缩小画笔宽度影响的 rect.X = x1 - 2; rect.Y = y1 - 3; rect.Width = i_width - rect.X + 2; rect.Height = i_height - rect.Y + 3; //判断如果太小,就给个最小值吧 if (rect.Width < 8) rect.Width = 8; if (rect.Height < 8) rect.Height = 8; return rect; } } }