diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs index 12bd2ba..6da0e28 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs @@ -76,6 +76,7 @@ namespace AGVMapEditor.Forms this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.button3 = new System.Windows.Forms.Button(); + this.toolStripButton2 = new System.Windows.Forms.ToolStripButton(); this.statusStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); @@ -483,7 +484,8 @@ namespace AGVMapEditor.Forms // this.toolStrip4.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.btDirDelete, - this.btMakeDirdata}); + this.btMakeDirdata, + this.toolStripButton2}); this.toolStrip4.Location = new System.Drawing.Point(0, 0); this.toolStrip4.Name = "toolStrip4"; this.toolStrip4.Size = new System.Drawing.Size(292, 25); @@ -560,6 +562,16 @@ namespace AGVMapEditor.Forms this.button3.UseVisualStyleBackColor = true; this.button3.Click += new System.EventHandler(this.button3_Click); // + // toolStripButton2 + // + this.toolStripButton2.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image"))); + this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButton2.Name = "toolStripButton2"; + this.toolStripButton2.Size = new System.Drawing.Size(54, 22); + this.toolStripButton2.Text = "Clear"; + this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -650,5 +662,6 @@ namespace AGVMapEditor.Forms private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button3; + private System.Windows.Forms.ToolStripButton toolStripButton2; } } \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs index f53f8f3..f4ad0ad 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs @@ -107,6 +107,7 @@ namespace AGVMapEditor.Forms { _mapCanvas = new UnifiedAGVCanvas(); _mapCanvas.Dock = DockStyle.Fill; + _mapCanvas.Mode = UnifiedAGVCanvas.CanvasMode.Edit; // 이벤트 연결 _mapCanvas.NodeAdded += OnNodeAdded; @@ -1496,15 +1497,15 @@ namespace AGVMapEditor.Forms // 기존 목록을 모두 지울지 물어보고 var result = MessageBox.Show( - "기존 설정된 마그넷 방향 정보를 모두 초기화하시겠습니까?\n'예'를 선택하면 모든 방향 정보가 삭제된 후 재설정됩니다.\n'아니오'를 선택하면 기존 정보는 유지되고 없는 부분만 추가됩니다.", + "마그넷방향을 자동 생성할까요? 없는 부분만 추가됩니다.", "마그넷 방향 자동 생성", - MessageBoxButtons.YesNoCancel, + MessageBoxButtons.YesNo, MessageBoxIcon.Question); - if (result == DialogResult.Cancel) + if (result != DialogResult.Yes) return; - bool clearAll = (result == DialogResult.Yes); + bool clearAll = false;// (result == DialogResult.Yes); int updateCount = 0; @@ -1639,5 +1640,38 @@ namespace AGVMapEditor.Forms else if (info.Direction == MagnetPosition.S) button2.BackColor = Color.Lime; else if (info.Direction == MagnetPosition.R) button3.BackColor = Color.Lime; } + + private void toolStripButton2_Click(object sender, EventArgs e) + { + var result = MessageBox.Show( + "기존 설정된 마그넷 방향 정보를 모두 초기화하시겠습니까?", + "마그넷 방향 일괄 삭제", + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + + if (result == DialogResult.Cancel) + return; + + bool clearAll = (result == DialogResult.Yes); + + int updateCount = 0; + + foreach (var node in this._mapCanvas.Nodes) + { + // 연결 노드가 3개 이상인 노드들을 찾아서 + if (node.Type == NodeType.Normal && node is MapNode mapNode) + { + if (clearAll) + { + if (mapNode.MagnetDirections != null) + mapNode.MagnetDirections.Clear(); + else mapNode.MagnetDirections = new Dictionary(); + } + } + } + + // 현재 선택된 노드의 속성창 및 리스트 갱신 + UpdateNodeProperties(); + } } } \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx index 4cc04c8..8cc428a 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx @@ -123,15 +123,6 @@ 249, 17 - - 17, 56 - - - 462, 17 - - - 249, 17 - @@ -148,6 +139,57 @@ nOccAdABIDXXE1nzAAAAAElFTkSuQmCC + + 17, 56 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK + YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X + /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t + I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM + cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh + 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD + lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A + HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb + 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC + nOccAdABIDXXE1nzAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK + YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X + /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t + I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM + cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh + 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD + lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A + HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb + 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC + nOccAdABIDXXE1nzAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK + YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X + /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t + I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM + cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh + 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD + lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A + HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb + 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC + nOccAdABIDXXE1nzAAAAAElFTkSuQmCC + + + + 462, 17 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 @@ -175,20 +217,6 @@ YIGDKaeH7rEGFFd1IN1M4c5nAYIcIXLXvmW+uOKfXMvpRO9rFnzJi9lqBKPZYVCedzYsH6SQ2l+Eu2SD bfNyWeHqqhbxahSCGIM2MwSKrYzDWboBx5sxIsP6yvTPH0lk3YoGI9lhaB8NQZO+gl8Dj7SN1tpAvgAA AABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHdSURBVDhPnZLra9NgFMb3T/hV8b8YFP+efZE5RL+qQxEV - dN6+OXfBTynNZtYmbeKSxfSS1pDSNq29UEpJW9tSULT6lvXCI+8LicTpij4QQs45z+85kLNSqVRQLpdR - KpVQLBZRKBSQz+dh2zZ9X1hZJsdxsFgszjzdbpdBDMM4H0KTqcF1XZbcbrd9CK1ZlnU+hK5Mh2ka/c7l - cvZ4PMZsNmN1CjRN8+8QmuoNplKp03Q67U4mEwy/dPDeOWS9VquFZDL5ZwhN9laez+eg5tHXT3ga3cDD - gzXozgHrNZtN6LoOSZKCEMuyyGg0YkPT6RSDzx1sRa/h1btb2NXu4ll0w4c0Gg2oqhqEZLPZK6ZpkuFw - yIY+uh/w6HANr4/v4I3+AHvavQCkXq9DluUgJJPJhFRVJYPBgA3VOnk8Edaxc7zpQ7aO1qEWw6xfrVYh - iiI4jvsFMQwjpCgK6ff7ZyD7J/fxUrqBF0c3MZtP2RbxeByRSOSSD6DSNC2USCRIr9fzIY/fXsXz2HVs - K5v4/uObb+Y47nLA7EmWZQahl8jWdW1sK7cxOSXLzZ5EUQzFYjFCL9H7xdQsSdJysydBEFYFQSD0wGq1 - 2r+ZPfE8v8rzPPkvsycKCYfDF3+ve/oJ+zEPR++RdtEAAAAASUVORK5CYII= @@ -217,6 +245,20 @@ lIotLMtCsVh8lQG4PM/L2bZNlstlBjno78Ds90jcG+zJLjMrivL6yCzlOI6A8EsUkEUP1PsItk/Om6UM w8jpuk74JcpfzM2maZ43S2madqlpGuEHNhwO/80sparqpaqq5L/MUhxSKBRe/l6X+gWA2x2MFEPZrwAA AABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHdSURBVDhPnZLra9NgFMb3T/hV8b8YFP+efZE5RL+qQxEV + dN6+OXfBTynNZtYmbeKSxfSS1pDSNq29UEpJW9tSULT6lvXCI+8LicTpij4QQs45z+85kLNSqVRQLpdR + KpVQLBZRKBSQz+dh2zZ9X1hZJsdxsFgszjzdbpdBDMM4H0KTqcF1XZbcbrd9CK1ZlnU+hK5Mh2ka/c7l + cvZ4PMZsNmN1CjRN8+8QmuoNplKp03Q67U4mEwy/dPDeOWS9VquFZDL5ZwhN9laez+eg5tHXT3ga3cDD + gzXozgHrNZtN6LoOSZKCEMuyyGg0YkPT6RSDzx1sRa/h1btb2NXu4ll0w4c0Gg2oqhqEZLPZK6ZpkuFw + yIY+uh/w6HANr4/v4I3+AHvavQCkXq9DluUgJJPJhFRVJYPBgA3VOnk8Edaxc7zpQ7aO1qEWw6xfrVYh + iiI4jvsFMQwjpCgK6ff7ZyD7J/fxUrqBF0c3MZtP2RbxeByRSOSSD6DSNC2USCRIr9fzIY/fXsXz2HVs + K5v4/uObb+Y47nLA7EmWZQahl8jWdW1sK7cxOSXLzZ5EUQzFYjFCL9H7xdQsSdJysydBEFYFQSD0wGq1 + 2r+ZPfE8v8rzPPkvsycKCYfDF3+ve/oJ+zEPR++RdtEAAAAASUVORK5CYII= @@ -404,36 +446,6 @@ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC nOccAdABIDXXE1nzAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK - YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X - /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t - I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM - cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh - 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD - lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A - HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb - 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC - nOccAdABIDXXE1nzAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK - YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X - /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t - I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM - cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh - 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD - lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A - HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb - 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC - nOccAdABIDXXE1nzAAAAAElFTkSuQmCC \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs index e307c4f..5fef289 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs @@ -72,6 +72,9 @@ namespace AGVNavigationCore.Controls DrawDragGhost(g); } + // 마그넷 방향 텍스트 그리기 (노드 위에 표시) + DrawMagnetDirections(g); + // AGV 그리기 DrawAGVs(g); @@ -105,6 +108,105 @@ namespace AGVNavigationCore.Controls } + private void DrawMagnetDirections(Graphics g) + { + if (_nodes == null) return; + + using (var font = new Font("Arial", 8, FontStyle.Bold)) + using (var brushS = new SolidBrush(Color.Magenta)) + using (var brushL = new SolidBrush(Color.Green)) + using (var brushR = new SolidBrush(Color.Blue)) + using (var brushBg = new SolidBrush(Color.FromArgb(180, 255, 255, 255))) + { + foreach (var node in _nodes) + { + if (node.MagnetDirections != null && node.MagnetDirections.Count > 0) + { + foreach (var kvp in node.MagnetDirections) + { + var targetId = kvp.Key; + var dir = kvp.Value; + var targetNode = _nodes.FirstOrDefault(n => n.Id == targetId); + + if (targetNode != null) + { + // 방향 텍스트 위치 계산 (출발 -> 도착 벡터의 일정 거리 지점) + var start = node.Position; + var end = targetNode.Position; + var angle = Math.Atan2(end.Y - start.Y, end.X - start.X); + + // 박스(텍스트) 중심 위치: 약 40px 거리 + var boxDist = 40; + var boxX = start.X + boxDist * Math.Cos(angle); + var boxY = start.Y + boxDist * Math.Sin(angle); + + string text = dir.ToString(); + + Color color = Color.Blue; + if (dir == MagnetPosition.L) color = Color.LimeGreen; + else if (dir == MagnetPosition.R) color = Color.Red; + + // 화살표 및 텍스트 설정 + using (var arrowBrush = new SolidBrush(color)) + using (var arrowPen = new Pen(color, 2)) // 두께 약간 증가 + using (var textBrush = new SolidBrush(color)) + { + // 1. 화살표 그리기 (박스를 가로지르는 선) + // 시작점: 노드 근처 (25px) + // 끝점: 박스 너머 (55px) + var arrowStartDist = 25; + var arrowEndDist = 55; + + var pStart = new PointF((float)(start.X + arrowStartDist * Math.Cos(angle)), (float)(start.Y + arrowStartDist * Math.Sin(angle))); + var pEnd = new PointF((float)(start.X + arrowEndDist * Math.Cos(angle)), (float)(start.Y + arrowEndDist * Math.Sin(angle))); + + // 화살표 선 그리기 + g.DrawLine(arrowPen, pStart, pEnd); + + // 화살표 머리 그리기 (끝점에) + var arrowSize = 6; + var pHead1 = new PointF((float)(pEnd.X + arrowSize * Math.Cos(angle)), (float)(pEnd.Y + arrowSize * Math.Sin(angle))); // 뾰족한 끝 + // 삼각형 머리 (채우기) + var pBackL = new PointF((float)(pEnd.X + arrowSize * Math.Cos(angle + 2.5)), (float)(pEnd.Y + arrowSize * Math.Sin(angle + 2.5))); + var pBackR = new PointF((float)(pEnd.X + arrowSize * Math.Cos(angle - 2.5)), (float)(pEnd.Y + arrowSize * Math.Sin(angle - 2.5))); + + // pHead1이 가장 먼 쪽이 되도록 조정 (pEnd가 삼각형의 뒷부분 중심이 되도록) + // pEnd에서 시작해서 앞으로 나가는 삼각형 + // pTip = pEnd + size * angle + // pBackL = pEnd + size/2 * angle_back_L (약간 뒤로) + // 현재 코드는 pEnd를 중심으로, pHead1이 앞, pBackL/R이 뒤... 가 아니라 + // pHead1, pBackK, pBackR로 삼각형을 그림. + // pHead1이 팁. + g.FillPolygon(arrowBrush, new PointF[] { pHead1, pBackL, pBackR }); + + // 2. 텍스트 그리기 (화살표 위에 박스, 그 위에 텍스트) + var textSize = g.MeasureString(text, font); + var textPoint = new PointF((float)(boxX - textSize.Width / 2), (float)(boxY - textSize.Height / 2)); + + //편집모드에서만 글자를 표시한다. + if(Mode == CanvasMode.Edit) + { + // 텍스트 배경 (반투명 - 선이 은은하게 보이도록 투명도 조절하거나, 가독성을 위해 불투명하게 처리) + // 사용자가 "박스를 가로지르는" 느낌을 원했으므로 선이 보여야 함. 하지만 텍스트 가독성도 필요. + // 배경을 아주 옅게 (Alpha 100정도) 처리하여 선이 보이게 함. + using (var translucentBg = new SolidBrush(Color.FromArgb(120, 255, 255, 255))) + { + g.FillRectangle(translucentBg, textPoint.X - 1, textPoint.Y - 1, textSize.Width + 2, textSize.Height + 2); + } + g.DrawString(text, font, textBrush, textPoint); + } + + + + + } + } + } + } + } + } + } + void DrawAlertMessage(Graphics g) { if (showalert == false) return; diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs index 80ef678..e1fd758 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs @@ -157,31 +157,20 @@ namespace AGVNavigationCore.PathFinding.Planning //갈림길에 있다면 미리 방향을 저장해준다. if ((node.ConnectedNodes?.Count ?? 0) > 2 && nextNode != null) { - switch (node.RfidId) + //다음 노드ID를 확인해서 마그넷 방향 데이터를 찾는다. + if (node.MagnetDirections.ContainsKey(nextNode.Id) == false) { - case 6: - if (nextNode.RfidId == 7) - magnetDirection = MagnetDirection.Left; - else if (nextNode.RfidId == 13) - magnetDirection = MagnetDirection.Right; - else - return AGVPathResult.CreateFailure($"{node.ID2}->{nextNode.ID2} 의 (목표)갈림길 방향이 입력되지 않았습니다", 0, 0); - break; - case 7: - if (nextNode.RfidId == 6) - magnetDirection = MagnetDirection.Right; - else - return AGVPathResult.CreateFailure( $"{node.ID2}->{nextNode.ID2} 의 (목표)갈림길 방향이 입력되지 않았습니다", 0, 0); - break; - case 13: - if (nextNode.RfidId == 6) - magnetDirection = MagnetDirection.Left; - else - return AGVPathResult.CreateFailure( $"{node.ID2}->{nextNode.ID2} 의 (목표)갈림길 방향이 입력되지 않았습니다", 0, 0); - break; - default: - return AGVPathResult.CreateFailure( $"{node.ID2}->{nextNode.ID2} 의 (시작)갈림길 방향이 입력되지 않았습니다", 0, 0); + return AGVPathResult.CreateFailure($"{node.ID2}->{nextNode.ID2} 의 (목표)갈림길 방향이 입력되지 않았습니다", 0, 0); } + else + { + var magdir = node.MagnetDirections[nextNode.Id].ToString(); + if (magdir == "L") magnetDirection = MagnetDirection.Left; + else if (magdir == "R") magnetDirection = MagnetDirection.Right; + + } + + } var nodeInfo = new NodeMotorInfo(i + 1, node.Id, node.RfidId, prevDirection, nextNode, magnetDirection); diff --git a/Cs_HMI/AGVLogic/AGVSimulator/Forms/SimulatorForm.cs b/Cs_HMI/AGVLogic/AGVSimulator/Forms/SimulatorForm.cs index 4d3b72e..89910a8 100644 --- a/Cs_HMI/AGVLogic/AGVSimulator/Forms/SimulatorForm.cs +++ b/Cs_HMI/AGVLogic/AGVSimulator/Forms/SimulatorForm.cs @@ -186,6 +186,7 @@ namespace AGVSimulator.Forms { _simulatorCanvas = new UnifiedAGVCanvas(); _simulatorCanvas.Dock = DockStyle.Fill; + _simulatorCanvas.Mode = UnifiedAGVCanvas.CanvasMode.Emulator; // 목적지 선택 이벤트 구독 _simulatorCanvas.NodesSelected += OnTargetNodeSelected;