using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AGVEmulator.UC { public partial class AgvViewer : Control { public AgvViewer() { InitializeComponent(); // Set Optimized Double Buffer to reduce flickering this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // Redraw when resized this.SetStyle(ControlStyles.ResizeRedraw, true); } public class TagArgs : EventArgs { public string Data { get; set; } public bool Active { get; set; } public TagArgs(string tag,bool act) { this.Data = tag; this.Active = act; } } public event EventHandler TagTouched; public event EventHandler MarkTouched; public event EventHandler Command; public bool StopbyMark { get; set; } public float mpos = 100; public float posmax = 1200; public float posmin = 0; public float mspd = 10; public System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch(); public Font FontTag { get; set; } public Font FontMrk { get; set; } public int dir = 1; public class ptdata { public float pos { get; set; } = 0f; public string data { get; set; } = string.Empty; public Boolean active { get; set; } = false; } public ptdata[] listMRK { get; set; } public ptdata[] listTAG { get; set; } public string lasttag { get; set; } = string.Empty; public string lasttagdir { get; set; } = string.Empty; public string lastmark { get; set; } = string.Empty; public string lastmarkdir { get; set; } = string.Empty; protected override void OnPaint(PaintEventArgs pe) { pe.Graphics.Clear(this.BackColor); var r = new Rectangle(DisplayRectangle.Left + Padding.Left, DisplayRectangle.Top + Padding.Top, DisplayRectangle.Width - Padding.Right - Padding.Left - 1, DisplayRectangle.Height - Padding.Top - Padding.Bottom - 1); // pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), DisplayRectangle); pe.Graphics.DrawRectangle(Pens.Black, r); var ptwidth = 25; var ptheight = 35; if (listMRK != null && listMRK.Any() && FontMrk != null) { foreach (var item in listMRK) { var x = r.Left + ((item.pos * 1f) / posmax) * r.Width; var rr = new RectangleF(x - ptwidth, r.Top + r.Height / 2f - ptheight / 2f, ptwidth * 2, ptheight); pe.Graphics.DrawLine(Pens.Gray, x, r.Top, x, r.Bottom); pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(120, Color.Gold)), rr); pe.Graphics.DrawRectangle(Pens.DimGray, rr.Left, rr.Top, rr.Width, rr.Height); pe.Graphics.DrawString(item.data, FontMrk, Brushes.Gray, rr, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, }); } } ptwidth = 15; if (listTAG != null && listTAG.Any() && FontTag != null) { var lst = listTAG.Where(t => t.data.EndsWith("1")); foreach (var item in lst) { var x = r.Left + ((item.pos * 1f) / posmax) * r.Width; var rr = new RectangleF(x - ptwidth, r.Top + 5, ptwidth * 2, 15); pe.Graphics.DrawLine(Pens.Orange, x, r.Top, x, rr.Top); pe.Graphics.FillRectangle(Brushes.Orange, rr); pe.Graphics.DrawRectangle(Pens.DimGray, rr.Left, rr.Top, rr.Width, rr.Height); pe.Graphics.DrawString(item.data, FontTag, Brushes.Black, rr, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, }); } lst = listTAG.Where(t => t.data.EndsWith("0")); foreach (var item in lst) { var x = r.Left + ((item.pos * 1f) / posmax) * r.Width; var rr = new RectangleF(x - ptwidth, r.Bottom - 20, ptwidth * 2, 15); pe.Graphics.DrawLine(Pens.Orange, x, rr.Bottom, x, r.Bottom); pe.Graphics.FillRectangle(Brushes.Orange, rr); pe.Graphics.DrawRectangle(Pens.DimGray, rr.Left, rr.Top, rr.Width, rr.Height); pe.Graphics.DrawString(item.data, FontTag, Brushes.Black, rr, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, }); } } var posX = r.Left + (mpos / posmax) * r.Width; var posY = r.Top + r.Height / 2f; var boxw = r.Width * 0.030f; var boxh = r.Height * 0.15f; var box = new RectangleF(posX - boxw, posY - boxh, boxw * 2, boxh * 2); var box2 = new RectangleF(box.Left - 5, box.Top + 3, 10, box.Height - 6); for (int i = 0; i < posmax; i += 100) { var x = r.Left + ((i * 1f) / posmax) * r.Width; pe.Graphics.DrawLine(Pens.Black, x, r.Bottom - 3, x, r.Bottom); if (i > 0) pe.Graphics.DrawString($"{i / 10f}m", this.Font, Brushes.Black, x - 12, r.Bottom - 15); } pe.Graphics.FillRectangle(Brushes.LightSkyBlue, box); pe.Graphics.DrawRectangle(Pens.Black, box.Left, box.Top, box.Width, box.Height); pe.Graphics.DrawLine(new Pen(Color.Black, 4), posX, box.Top - 5, posX, box.Bottom + 5); pe.Graphics.FillRectangle(Brushes.Gold, box2); pe.Graphics.DrawRectangle(Pens.Black, box2.Left, box2.Top, box2.Width, box2.Height); //pe.Graphics.DrawString((mpos / 10f).ToString("N1") + "m", this.Font, Brushes.Black, box, new StringFormat //{ // Alignment = StringAlignment.Center, // LineAlignment = StringAlignment.Center, //}); if (StopbyMark) pe.Graphics.DrawString("!MRK-STP!", this.Font, Brushes.Blue, r.Left+2, r.Top+2); if (wat.IsRunning) { var newpos = mspd * (wat.ElapsedMilliseconds / 1000f); if (dir < 0) //forward { if (mpos - newpos < 0) mpos = posmax; else mpos -= newpos; //내위치주변에 마커가 있는지 본다 var mlist = listMRK.Where(t => t.pos <= mpos && (mpos - t.pos) < 10); var mrk = mlist.FirstOrDefault(); if (mrk != null) { //대상마커가있다 if (lastmark.Equals(mrk.data) == false || lastmarkdir.Equals("F") == false) { lastmark = mrk.data; lastmarkdir = "F"; mrk.active = true; MarkTouched?.Invoke(this, new TagArgs(mrk.data,true)); if(StopbyMark) { Command?.Invoke(this, new TagArgs("stop",true)); StopbyMark = false; } } } else { if (string.IsNullOrEmpty(lastmark) == false) { foreach(var item in listMRK.Where(t=>t.active)) { item.active = false; MarkTouched?.Invoke(this, new TagArgs(item.data,false)); } } } //주변태그확인 var tlist = listTAG.Where(t => t.pos <= mpos && (mpos - t.pos) < 10); var tag = tlist.FirstOrDefault(); if (tag != null) { //대상마커가있다 if (lasttag.Equals(tag.data) == false || lasttagdir.Equals("F") == false) { lasttag = tag.data; lasttagdir = "F"; TagTouched?.Invoke(this, new TagArgs(tag.data, true)); } } } else //backward { if (mpos + newpos > posmax) mpos = 0; else mpos += newpos; //내위치주변에 마커가 있는지 본다 var mlist = listMRK.Where(t => t.pos >= mpos && (t.pos - mpos) < 10); var mrk = mlist.FirstOrDefault(); if (mrk != null) { //대상마커가있다 if (lastmark.Equals(mrk.data) == false || lastmarkdir.Equals("B") == false) { lastmark = mrk.data; lastmarkdir = "B"; mrk.active = true; MarkTouched?.Invoke(this, new TagArgs(mrk.data, true)); if (StopbyMark) { Command?.Invoke(this, new TagArgs("stop", true)); StopbyMark = false; } } } else { if (string.IsNullOrEmpty(lastmark) == false) { foreach (var item in listMRK.Where(t => t.active)) { item.active = false; MarkTouched?.Invoke(this, new TagArgs(item.data, false)); } } } //주변태그확인 var tlist = listTAG.Where(t => t.pos >= mpos && (t.pos - mpos) < 10); var tag = tlist.FirstOrDefault(); if (tag != null) { //대상마커가있다 if (lasttag.Equals(tag.data) == false || lasttagdir.Equals("B") == false) { lasttag = tag.data; lasttagdir = "B"; TagTouched?.Invoke(this, new TagArgs(tag.data, true)); } } } wat.Restart(); } } } }